/*
 * Copyright 2000-2012 JetBrains s.r.o.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.intellij.cvsSupport2.cvsoperations.cvsMessages;

import com.intellij.cvsSupport2.application.CvsEntriesManager;
import com.intellij.cvsSupport2.cvshandlers.CvsMessagePattern;
import com.intellij.cvsSupport2.cvsoperations.common.UpdatedFilesManager;
import com.intellij.util.PatternUtil;
import com.intellij.util.containers.HashMap;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
import org.netbeans.lib.cvsclient.admin.Entry;
import org.netbeans.lib.cvsclient.command.update.UpdateFileInfo;
import org.netbeans.lib.cvsclient.command.update.UpdatedFileInfo;
import org.netbeans.lib.cvsclient.event.EventManager;
import org.netbeans.lib.cvsclient.event.IEntryListener;
import org.netbeans.lib.cvsclient.event.IFileInfoListener;
import org.netbeans.lib.cvsclient.event.IMessageListener;
import org.netbeans.lib.cvsclient.file.FileObject;
import org.netbeans.lib.cvsclient.file.ICvsFileSystem;

import java.io.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
import java.util.regex.Pattern;

/**
 * author: lesya
 */
public class CvsMessagesTranslator implements IFileInfoListener, IMessageListener, IEntryListener {

  @NonNls private static final CvsMessagePattern[] ERRORS_PATTERNS = new CvsMessagePattern[]{
    new CvsMessagePattern("cvs [* aborted]*"),
    new CvsMessagePattern("Usage: cvs* server*"),
    new CvsMessagePattern("cvs*: invalid option*"),
    new CvsMessagePattern(new String[]{"cvs checkout: could not check out ", "*"}, 2),
    new CvsMessagePattern("cvs* update: could not merge revision * of *: No such file or directory"),
    new CvsMessagePattern(new String[]{"cvs* update: could not patch ", "*", "; will refetch"}, 2),
    new CvsMessagePattern("dying gasps from * unexpected"),
    new CvsMessagePattern("end of file from server (consult above messages if any)"),
    new CvsMessagePattern("\\*PANIC\\* administration files missing"),
    new CvsMessagePattern(new String[]{"cvs*: Up-to-date check failed for `", "*", "'"}, 2),
    new CvsMessagePattern("cvs*: cannot add file on non-branch tag *"),
    new CvsMessagePattern("Cannot access *"),
    new CvsMessagePattern("error  Permission denied"),
    new CvsMessagePattern(new String[]{"cvs*: ", "*", " already exists, with version number *"}, 2),
    new CvsMessagePattern(new String[]{"cvs*: cannot commit with sticky date for file `", "*", "'"}, 2),
    new CvsMessagePattern(new String[]{"cvs*: nothing known about `", "*", "'"}, 2),
    new CvsMessagePattern("cvs*: sticky tag `*' for file `*' is not a branch"),
    new CvsMessagePattern("cvs*: ERROR: cannot mkdir * -- not added: No such file or directory"),
    new CvsMessagePattern(new String[]{"cvs: nothing known about ", "*"}, 2),
    new CvsMessagePattern("Root * must be an absolute pathname"),
    new CvsMessagePattern("protocol error: *"),
    new CvsMessagePattern("cvs* tag: nothing known about *"),
    new CvsMessagePattern("cvs* tag: cannot*"),
    new CvsMessagePattern("cvs* tag:* failed*"),
    new CvsMessagePattern("cvs* tag: Not removing branch tag `*' from `*,v'."),
    new CvsMessagePattern("cvs tag: *: Not moving branch tag `*' from * to *."),
    new CvsMessagePattern(new String[]{"cvs*: failed to create lock directory for `", "*", "' (*/#cvs.lock): No such file or directory"}, 2)
  };

  private static final CvsMessagePattern[] WARNINGS_PATTERNS = new CvsMessagePattern[]{
    new CvsMessagePattern("cvs server: cannot open *: Permission denied"),
    new CvsMessagePattern("cvs server: cannot make path to *: Permission denied"),
    new CvsMessagePattern("cvs server: cannot find module `*' - ignored"),
    new CvsMessagePattern("W * : * already exists on version * : NOT MOVING tag to version *"),
    new CvsMessagePattern("W * : * already exists on branch * : NOT MOVING tag to branch *"),
    new CvsMessagePattern(new String[]{"cvs server: ", "*", " added independently by second party"}, 2),
    new CvsMessagePattern("cvs server: failed to create lock directory for `*' (*#cvs.lock): No such file or directory"),
    new CvsMessagePattern("cvs server: failed to obtain dir lock in repository `*'"),
    new CvsMessagePattern("cvs*: warning: *")
  };

  private static final Pattern[] FILE_MESSAGE_PATTERNS = new Pattern[]{PatternUtil.fromMask("cvs*: Updating*"),
    PatternUtil.fromMask("Directory * added to the repository"), PatternUtil.fromMask("cvs*: scheduling file `*' for addition"),
    PatternUtil.fromMask("cvs *: [*] waiting for *'s lock in *"), PatternUtil.fromMask("RCS file: *,v"),
    PatternUtil.fromMask("cvs*: Tagging*"), PatternUtil.fromMask("cvs add: scheduling file `*' for addition"),
    PatternUtil.fromMask("cvs rlog: Logging*")
  };

  private static final Pattern[] MESSAGE_PATTERNS = new Pattern[]{PatternUtil.fromMask("cvs *: [*] waiting for *'s lock in *")};

  private final CvsMessagesListener myListener;
  private final ICvsFileSystem myCvsFileSystem;
  private final UpdatedFilesManager myUpdatedFilesManager;
  private final String myCvsRoot;
  private final Map<File, Object> myFileToInfoMap = new HashMap<File, Object>();

  private final Collection<String> myPreviousErrorMessages = new ArrayList<String>();
  @NonNls private static final String CORRECT_ABOVE_ERRORS_FIRST_PREFIX = "correct above errors first";

  enum MessageType { MESSAGE, FILE_MESSAGE, WARNING, ERROR }
  private MessageType lastMessage = null;

  public CvsMessagesTranslator(CvsMessagesListener listener,
                               ICvsFileSystem cvsFileSystem,
                               UpdatedFilesManager mergedFilesCollector,
                               String cvsroot) {
    myListener = listener;
    myCvsFileSystem = cvsFileSystem;
    myUpdatedFilesManager = mergedFilesCollector;
    myCvsRoot = cvsroot;
  }

  public void fileInfoGenerated(Object info) {
    if (info instanceof UpdateFileInfo) {
      final UpdateFileInfo updateFileInfo = (UpdateFileInfo)info;
      final File file = updateFileInfo.getFile();
      if (!myUpdatedFilesManager.fileIsNotUpdated(file) && !myFileToInfoMap.containsKey(file)) {
        myFileToInfoMap.put(file, updateFileInfo);
      }
    }
    else if (info instanceof UpdatedFileInfo) {
      final UpdatedFileInfo updatedFileInfo = (UpdatedFileInfo)info;
      final File file = updatedFileInfo.getFile();
      if (!myUpdatedFilesManager.fileIsNotUpdated(file)) {
        myFileToInfoMap.put(file, updatedFileInfo);
      }
    }
  }

  public void gotEntry(FileObject fileObject, Entry entry) {}

  public void messageSent(String message, final byte[] byteMessage, boolean error, boolean tagged) {
    myListener.addMessage(new MessageEvent(message, error, tagged));
    if (message.isEmpty()) {
      return;
    }

    if (isFileMessage(message)) {
      lastMessage = MessageType.FILE_MESSAGE;
      myListener.addFileMessage(message, myCvsFileSystem);
      return;
    }
    if (isMessage(message)) {
      lastMessage = MessageType.MESSAGE;
      myListener.addMessage(message);
      return;
    }

    final CvsMessagePattern errorMessagePattern = getErrorMessagePattern(message, ERRORS_PATTERNS);
    if (errorMessagePattern != null) {
      if (message.contains(CORRECT_ABOVE_ERRORS_FIRST_PREFIX)) {
        for (String s : myPreviousErrorMessages) {
          myListener.addError(s, null, myCvsFileSystem, myCvsRoot, false);
        }
        myPreviousErrorMessages.clear();
        return;
      }
      final String relativeFileName = errorMessagePattern.getRelativeFileName(message);
      lastMessage = MessageType.ERROR;
      myListener.addError(message, relativeFileName, myCvsFileSystem, myCvsRoot, false);
      return;
    }
    final CvsMessagePattern warningMessagePattern = getErrorMessagePattern(message, WARNINGS_PATTERNS);
    if (warningMessagePattern != null) {
      lastMessage = MessageType.WARNING;
      myListener.addError(message,warningMessagePattern.getRelativeFileName(message), myCvsFileSystem, myCvsRoot, true);
      return;
    }

    if (message.trim().isEmpty()) return;
    if (lastMessage == MessageType.ERROR) {
      myListener.addError(message, null, myCvsFileSystem, myCvsRoot, false);
    } else if (lastMessage == MessageType.WARNING) {
      myListener.addError(message, null, myCvsFileSystem, myCvsRoot, true);
    } else if (error) {
      myPreviousErrorMessages.add(message);
    }
  }

  private static boolean isFileMessage(String message) {
    for (Pattern pattern : FILE_MESSAGE_PATTERNS) {
      if (pattern.matcher(message).matches()) return true;
    }
    return false;
  }

  private static boolean isMessage(String message) {
    for (Pattern pattern : MESSAGE_PATTERNS) {
      if (pattern.matcher(message).matches()) return true;
    }
    return false;
  }

  @Nullable
  private static CvsMessagePattern getErrorMessagePattern(String message, CvsMessagePattern[] patterns) {
    for (CvsMessagePattern pattern : patterns) {
      if (pattern.matches(message)) {
        return pattern;
      }
    }
    return null;
  }

  public void registerTo(EventManager eventManager) {
    eventManager.addFileInfoListener(this);
    eventManager.addMessageListener(this);
  }

  public void operationCompleted() {
    if (!CvsEntriesManager.getInstance().isActive()) {
      return;
    }
    for (File file : myFileToInfoMap.keySet()) {
      addFileMessage(myFileToInfoMap.get(file), file);
    }
  }

  private void addFileMessage(Object info, File file) {
    if (info instanceof UpdateFileInfo) {
      addUpdateFileInfo(file, (UpdateFileInfo)info);
    }
    else if (info instanceof UpdatedFileInfo) {
      addUpdatedFileInfo(file, (UpdatedFileInfo)info);
    }
  }

  private void addUpdatedFileInfo(File file, UpdatedFileInfo updatedFileInfo) {
    if (!myUpdatedFilesManager.fileIsNotUpdated(file)) {
      myListener.addFileMessage(new FileMessage(updatedFileInfo, myUpdatedFilesManager));
    }
  }

  private void addUpdateFileInfo(File file, UpdateFileInfo updateFileInfo) {
    if (!myUpdatedFilesManager.fileIsNotUpdated(file)) {
      myListener.addFileMessage(new FileMessage(updateFileInfo, myUpdatedFilesManager, myUpdatedFilesManager));
    }
  }

  public void binaryMessageSent(final byte[] bytes) {}
}