/*
 *                 Sun Public License Notice
 *
 * The contents of this file are subject to the Sun Public License
 * Version 1.0 (the "License"). You may not use this file except in
 * compliance with the License. A copy of the License is available at
 * http://www.sun.com/
 *
 * The Original Code is NetBeans. The Initial Developer of the Original
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2000 Sun
 * Microsystems, Inc. All Rights Reserved.
 */
package org.netbeans.lib.cvsclient;

import com.intellij.util.concurrency.Semaphore;
import org.jetbrains.annotations.NonNls;
import org.netbeans.lib.cvsclient.command.CommandAbortedException;
import org.netbeans.lib.cvsclient.command.CommandException;
import org.netbeans.lib.cvsclient.command.IGlobalOptions;
import org.netbeans.lib.cvsclient.command.IOCommandException;
import org.netbeans.lib.cvsclient.connection.AuthenticationException;
import org.netbeans.lib.cvsclient.event.IEventSender;
import org.netbeans.lib.cvsclient.file.FileDetails;
import org.netbeans.lib.cvsclient.file.FileObject;
import org.netbeans.lib.cvsclient.io.IStreamLogger;
import org.netbeans.lib.cvsclient.progress.sending.IRequestsProgressHandler;
import org.netbeans.lib.cvsclient.request.*;
import org.netbeans.lib.cvsclient.response.DefaultResponseHandler;
import org.netbeans.lib.cvsclient.response.IResponseHandler;
import org.netbeans.lib.cvsclient.response.ResponseParser;
import org.netbeans.lib.cvsclient.response.ValidRequestsResponseHandler;
import org.netbeans.lib.cvsclient.util.BugLog;

import java.io.IOException;
import java.io.Reader;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

/**
 * @author Thomas Singer
 */
public final class RequestProcessor implements IRequestProcessor {

  // Fields =================================================================

  private final IGlobalOptions globalOptions;
  private final IClientEnvironment clientEnvironment;
  private final ResponseService responseServices;
  private final IStreamLogger streamLogger;
  private final ICvsCommandStopper commandStopper;
  @NonNls private static final String OS_NAME_PROPERTY = "os.name";
  @NonNls private static final String WINDOWS_PREFIX = "Windows";
  @NonNls private static final String CASE_REQUEST = "Case";
  @NonNls private static final String CVS_PASS_ENV_VARS_PROPERTY = "cvs.pass.env.vars";
  @NonNls private static final String NO = "no";
  private final long myTimeout;

  // Setup ==================================================================
  public RequestProcessor(IClientEnvironment clientEnvironment,
                          IGlobalOptions globalOptions,
                          IEventSender eventSender,
                          IStreamLogger streamLogger,
                          ICvsCommandStopper commandStopper) {
    this(clientEnvironment, globalOptions, eventSender, streamLogger, commandStopper, -1);
  }

  public RequestProcessor(IClientEnvironment clientEnvironment,
                          IGlobalOptions globalOptions,
                          IEventSender eventSender,
                          IStreamLogger streamLogger,
                          ICvsCommandStopper commandStopper, final long timeout) {
    myTimeout = timeout;
    BugLog.getInstance().assertNotNull(globalOptions);
    BugLog.getInstance().assertNotNull(clientEnvironment);
    BugLog.getInstance().assertNotNull(eventSender);
    BugLog.getInstance().assertNotNull(streamLogger);
    BugLog.getInstance().assertNotNull(commandStopper);

    this.globalOptions = globalOptions;
    this.clientEnvironment = clientEnvironment;
    this.responseServices = new ResponseService(eventSender);
    this.streamLogger = streamLogger;
    this.commandStopper = commandStopper;
  }

  // Implemented ============================================================

  public boolean processRequests(Requests requests, IRequestsProgressHandler communicationProgressHandler) throws CommandException,
                                                                                                                  AuthenticationException {
    IConnectionStreams connectionStreams = openConnection();
    try {
      return processRequests(requests, connectionStreams, communicationProgressHandler);
    }
    finally {
      connectionStreams.close();
    }
  }

  // Utils ==================================================================

  private IConnectionStreams openConnection() throws CommandException, AuthenticationException {
    clientEnvironment.getConnection().open(streamLogger);

    ConnectionStreams connectionStreams =
      new ConnectionStreams(clientEnvironment.getConnection(), streamLogger, clientEnvironment.getCharset());
    boolean exception = true;
    try {
      updateValidRequests(connectionStreams);

      sendRequest(new RootRequest(clientEnvironment.getConnection().getRepository()), connectionStreams);
      sendSetRequests(globalOptions, connectionStreams);
      // Handle gzip-compression
      if (globalOptions.isUseGzip() && isValidRequest(GzipStreamRequest.REQUEST)) {
        sendRequest(new GzipStreamRequest(), connectionStreams);

        connectionStreams.setGzipped();
      }

      //TODO: set variables

      sendRequest(new ValidResponsesRequest(), connectionStreams);

      sendRequest(new UseUnchangedRequest(), connectionStreams);
      sendGlobalOptionRequests(globalOptions, connectionStreams);

      if (System.getProperty(OS_NAME_PROPERTY).startsWith(WINDOWS_PREFIX) && isValidRequest(CASE_REQUEST)) {
        sendRequest(new CaseRequest(), connectionStreams);
      }

      exception = false;
      return connectionStreams;
    }
    catch (IOException ex) {
      BugLog.getInstance().showException(ex);
      throw new IOCommandException(ex);
    }
    finally {
      if (exception) {
        connectionStreams.close();
      }
    }
  }

  private void sendSetRequests(IGlobalOptions globalOptions, ConnectionStreams connectionStreams)
    throws CommandAbortedException, IOException {
    Map envVariables = globalOptions.getEnvVariables();
    if (envVariables == null) {
      return;
    }
    for (Iterator iterator = envVariables.keySet().iterator(); iterator.hasNext();) {
      String varName = (String)iterator.next();
      String varValue = (String)envVariables.get(varName);
      sendRequest(new SetRequest(varName, varValue), connectionStreams);
    }
  }

  private boolean processRequests(final Requests requests,
                                  final IConnectionStreams connectionStreams,
                                  final IRequestsProgressHandler communicationProgressHandler)
    throws CommandException, IOCommandException {

    BugLog.getInstance().assertNotNull(requests);

    /*final ProcessRequestsHelper helper = (myTimeout == -1) ?
                                         new DirectProcessRequestHelper() : new TimedOutProcessRequestHelper();*/
    final ProcessRequestsHelper helper = new DirectProcessRequestHelper();
    return helper.processRequests(requests, connectionStreams, communicationProgressHandler);
  }

  private abstract class ProcessRequestsHelper {
    protected IOException myIOException;
    protected CommandException myCommandException;
    protected boolean myResult;

    protected abstract void before();
    protected abstract void callRunnable(final Runnable runnable);
    protected abstract void afterInRunnable();
    protected abstract void after() throws CommandException;

    public boolean processRequests(final Requests requests,
                                   final IConnectionStreams connectionStreams,
                                   final IRequestsProgressHandler communicationProgressHandler)
      throws CommandException, IOCommandException {
      final Runnable runnable = new Runnable() {
        public void run() {
          try {
            checkCanceled();
            sendRequests(requests, connectionStreams, communicationProgressHandler);
            checkCanceled();

            sendRequest(requests.getResponseExpectingRequest(), connectionStreams);
            connectionStreams.flushForReading();

            myResult = handleResponses(connectionStreams, new DefaultResponseHandler());
          }
          catch (IOException e) {
            myIOException = e;
          }
          catch (CommandException e) {
            myCommandException = e;
          }
          finally {
            afterInRunnable();
          }
        }
      };

      before();
      callRunnable(runnable);
      if (myIOException != null) throw new IOCommandException(myIOException);
      if (myCommandException != null) throw myCommandException;
      after();

      return myResult;
    }
  }

  private class TimedOutProcessRequestHelper extends ProcessRequestsHelper {
    private final Semaphore mySemaphore;
    private Future<?> myFuture;

    private TimedOutProcessRequestHelper() {
      mySemaphore = new Semaphore();
    }

    @Override
    protected void before() {
      mySemaphore.down();
    }

    @Override
    protected void callRunnable(Runnable runnable) {
      myFuture = Executors.newSingleThreadExecutor().submit(runnable);

      final long tOut = (myTimeout < 20000) ? 20000 : myTimeout;
      while (true) {
        mySemaphore.waitFor(tOut);
        if (myFuture.isDone() || myFuture.isCancelled()) break;
        if (! commandStopper.isAlive()) break;
        commandStopper.resetAlive();
      }
    }

    @Override
    protected void afterInRunnable() {
      mySemaphore.up();
    }

    @Override
    protected void after() throws CommandException {
      if ((! myFuture.isDone() && (! myFuture.isCancelled()) && (! commandStopper.isAlive()))) {
        myFuture.cancel(true);
        throw new CommandException(new CommandAbortedException(), "Command execution timed out");
      }
    }
  }

  private class DirectProcessRequestHelper extends ProcessRequestsHelper {
    @Override
    protected void before() {
    }

    @Override
    protected void callRunnable(Runnable runnable) {
      runnable.run();
    }

    @Override
    protected void afterInRunnable() {
    }

    @Override
    protected void after() throws CommandException {
    }
  }

  private void sendRequests(Requests requests, IConnectionStreams connectionStreams, IRequestsProgressHandler communicationProgressHandler)
    throws CommandAbortedException, IOException {
    for (Iterator it = requests.getRequests().iterator(); it.hasNext();) {
      final IRequest request = (IRequest)it.next();

      sendRequest(request, connectionStreams);

      final FileDetails fileDetails = request.getFileForTransmission();
      if (fileDetails != null) {
        sendFile(fileDetails, connectionStreams);
      }

      communicationProgressHandler.requestSent(request);
    }
  }

  private void updateValidRequests(IConnectionStreams connectionStreams) throws CommandException, IOException {
    sendRequest(new ValidRequestsRequest(), connectionStreams);
    connectionStreams.flushForReading();
    handleResponses(connectionStreams, new ValidRequestsResponseHandler());

    if (responseServices.getValidRequests() == null) {
      throw new ValidRequestsExpectedException();
    }
  }

  private void sendGlobalOptionRequests(IGlobalOptions globalOptions, IConnectionStreams connectionStreams)
    throws CommandAbortedException, IOException {
    if (!isValidRequest(GlobalOptionRequest.REQUEST)) {
      return;
    }

    if (globalOptions.isCheckedOutFilesReadOnly()) {
      sendRequest(new GlobalOptionRequest("-r"), connectionStreams);
    }
    if (globalOptions.isDoNoChanges()) {
      sendRequest(new GlobalOptionRequest("-n"), connectionStreams);
    }
    if (globalOptions.isNoHistoryLogging()) {
      sendRequest(new GlobalOptionRequest("-l"), connectionStreams);
    }
    if (globalOptions.isSomeQuiet()) {
      sendRequest(new GlobalOptionRequest("-q"), connectionStreams);
    }
  }

  private boolean isValidRequest(String request) {
    return responseServices.getValidRequests().indexOf(request) >= 0;
  }

  private void sendRequest(IRequest request, IConnectionStreams connectionStreams) throws CommandAbortedException, IOException {
    checkCanceled();
    connectionStreams.getLoggedWriter().write(request.getRequestString());
  }

  private void checkCanceled() throws CommandAbortedException {
    if (commandStopper.isAborted()) {
      throw new CommandAbortedException();
    }
  }

  private boolean handleResponses(IConnectionStreams connectionStreams, IResponseHandler responseHandler)
    throws CommandException, IOException {
    //final ErrorDefendingResponseHandler proxy = new ErrorDefendingResponseHandler(myTimeout, responseHandler);

    final ResponseParser responseParser = new ResponseParser(responseHandler, clientEnvironment.getCharset());
    final StringBuilder responseBuffer = new StringBuilder(32);
    while (true) {
      readResponse(connectionStreams.getLoggedReader(), responseBuffer);
      checkCanceled();
      if (responseBuffer.length() == 0) {
        return false;
      }

      final Boolean result =
        responseParser.processResponse(responseBuffer.toString(), connectionStreams, responseServices, clientEnvironment);
      if (result != null) {
        return result.booleanValue();
      }

      checkCanceled();
      /*if (proxy.interrupt()) {
        throw new CommandException(null, "Aborted: consequent errors stream");
      }*/
    }
  }

  private static void readResponse(Reader reader, StringBuilder responseBuffer) throws IOException {
    responseBuffer.setLength(0);

    for (int chr = reader.read(); chr >= 0; chr = reader.read()) {
      if (chr == '\n' || chr == ' ') {
        break;
      }
      responseBuffer.append((char)chr);
    }
  }

  private void sendFile(FileDetails fileDetails, IConnectionStreams connectionStreams) throws IOException {
    final FileObject fileObject = fileDetails.getFileObject();

    if (fileDetails.isBinary()) {
      clientEnvironment.getLocalFileReader().transmitBinaryFile(fileObject, connectionStreams, clientEnvironment.getCvsFileSystem());
    }
    else {
      clientEnvironment.getLocalFileReader().transmitTextFile(fileObject, connectionStreams, clientEnvironment.getCvsFileSystem());
    }
  }
}
