/*
 * Copyright 2000-2009 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.openapi.vcs.changes;

import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.WriteExternalException;
import com.intellij.openapi.util.text.StringUtil;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;

import java.io.File;
import java.util.*;

class ChangeListManagerSerialization {
  @NonNls static final String ATT_ID = "id";
  @NonNls static final String ATT_NAME = "name";
  @NonNls static final String ATT_COMMENT = "comment";
  @NonNls static final String ATT_DEFAULT = "default";
  @NonNls static final String ATT_READONLY = "readonly";
  @NonNls static final String ATT_VALUE_TRUE = "true";
  @NonNls static final String ATT_CHANGE_TYPE = "type";
  @NonNls static final String ATT_CHANGE_BEFORE_PATH = "beforePath";
  @NonNls static final String ATT_CHANGE_AFTER_PATH = "afterPath";
  @NonNls static final String ATT_PATH = "path";
  @NonNls static final String ATT_MASK = "mask";
  @NonNls static final String NODE_LIST = "list";
  @NonNls static final String NODE_IGNORED = "ignored";
  @NonNls static final String NODE_CHANGE = "change";
  @NonNls static final String MANUALLY_REMOVED_FROM_IGNORED = "manually-removed-from-ignored";
  @NonNls static final String DIRECTORY_TAG = "directory";

  private final IgnoredFilesComponent myIgnoredIdeaLevel;
  private final ChangeListWorker myWorker;

  ChangeListManagerSerialization(final IgnoredFilesComponent ignoredIdeaLevel, final ChangeListWorker worker) {
    myIgnoredIdeaLevel = ignoredIdeaLevel;
    myWorker = worker;
  }

  @SuppressWarnings({"unchecked"})
  public void readExternal(final Element element) throws InvalidDataException {
    final List<Element> listNodes = element.getChildren(NODE_LIST);
    for (Element listNode : listNodes) {
      readChangeList(listNode);
    }
    final List<Element> ignoredNodes = element.getChildren(NODE_IGNORED);
    for (Element ignoredNode : ignoredNodes) {
      readFileToIgnore(ignoredNode);
    }
    Element manuallyRemovedFromIgnoredTag = element.getChild(MANUALLY_REMOVED_FROM_IGNORED);
    Set<String> manuallyRemovedFromIgnoredPaths = new HashSet<String>();
    if (manuallyRemovedFromIgnoredTag != null) {
      for (Element tag : manuallyRemovedFromIgnoredTag.getChildren(DIRECTORY_TAG)) {
        manuallyRemovedFromIgnoredPaths.add(tag.getAttributeValue(ATT_PATH));
      }
    }
    myIgnoredIdeaLevel.setDirectoriesManuallyRemovedFromIgnored(manuallyRemovedFromIgnoredPaths);
  }

  private void readChangeList(final Element listNode) {
    // workaround for loading incorrect settings (with duplicate changelist names)
    final String changeListName = listNode.getAttributeValue(ATT_NAME);
    LocalChangeList list = myWorker.getCopyByName(changeListName);
    if (list == null) {
      list = myWorker.addChangeList(listNode.getAttributeValue(ATT_ID), changeListName, listNode.getAttributeValue(ATT_COMMENT), false,
                                    null);
    }
    //noinspection unchecked
    final List<Element> changeNodes = listNode.getChildren(NODE_CHANGE);
    for (Element changeNode : changeNodes) {
      try {
        myWorker.addChangeToList(changeListName, readChange(changeNode), null);
      }
      catch (OutdatedFakeRevisionException e) {
        // Do nothing. Just skip adding outdated revisions to the list.
      }
    }

    if (ATT_VALUE_TRUE.equals(listNode.getAttributeValue(ATT_DEFAULT))) {
      myWorker.setDefault(list.getName());
    }
    if (ATT_VALUE_TRUE.equals(listNode.getAttributeValue(ATT_READONLY))) {
      list.setReadOnly(true);
    }
  }

  private void readFileToIgnore(final Element ignoredNode) {
    String path = ignoredNode.getAttributeValue(ATT_PATH);
    if (path != null) {
      Project project = myWorker.getProject();
      final IgnoredFileBean bean = path.endsWith("/") || path.endsWith(File.separator)
                                   ? IgnoredBeanFactory.ignoreUnderDirectory(path, project)
                                   : IgnoredBeanFactory.ignoreFile(path, project);
      myIgnoredIdeaLevel.add(bean);
    }
    String mask = ignoredNode.getAttributeValue(ATT_MASK);
    if (mask != null) {
      final IgnoredFileBean bean = IgnoredBeanFactory.withMask(mask);
      myIgnoredIdeaLevel.add(bean);
    }
  }

  public void writeExternal(Element element) throws WriteExternalException {
    final List<LocalChangeList> changeListList = myWorker.getListsCopy();
    for (LocalChangeList list : changeListList) {
      Element listNode = new Element(NODE_LIST);
      element.addContent(listNode);
      if (list.isDefault()) {
        listNode.setAttribute(ATT_DEFAULT, ATT_VALUE_TRUE);
      }
      if (list.isReadOnly()) {
        listNode.setAttribute(ATT_READONLY, ATT_VALUE_TRUE);
      }

      listNode.setAttribute(ATT_ID, list.getId());
      listNode.setAttribute(ATT_NAME, list.getName());
      String comment = list.getComment();
      if (comment != null) {
        listNode.setAttribute(ATT_COMMENT, comment);
      }
      List<Change> changes = new ArrayList<Change>(list.getChanges());
      Collections.sort(changes, new ChangeComparator());
      for (Change change : changes) {
        writeChange(listNode, change);
      }
    }
    final IgnoredFileBean[] filesToIgnore = myIgnoredIdeaLevel.getFilesToIgnore();
    for (IgnoredFileBean bean : filesToIgnore) {
      Element fileNode = new Element(NODE_IGNORED);
      element.addContent(fileNode);
      String path = bean.getPath();
      if (path != null) {
        fileNode.setAttribute("path", path);
      }
      String mask = bean.getMask();
      if (mask != null) {
        fileNode.setAttribute("mask", mask);
      }
    }
    Set<String> manuallyRemovedFromIgnored = myIgnoredIdeaLevel.getDirectoriesManuallyRemovedFromIgnored();
    if (!manuallyRemovedFromIgnored.isEmpty()) {
      Element list = new Element(MANUALLY_REMOVED_FROM_IGNORED);
      for (String path : manuallyRemovedFromIgnored) {
        list.addContent(new Element(DIRECTORY_TAG).setAttribute(ATT_PATH, path));
      }
      element.addContent(list);
    }
  }

  private static class ChangeComparator implements Comparator<Change> {
    @Override
    public int compare(@NotNull Change o1, @NotNull Change o2) {
      return Comparing.compare(o1.toString(), o2.toString());
    }
  }

  private static void writeChange(final Element listNode, final Change change) {
    Element changeNode = new Element(NODE_CHANGE);
    listNode.addContent(changeNode);
    changeNode.setAttribute(ATT_CHANGE_TYPE, change.getType().name());

    final ContentRevision bRev = change.getBeforeRevision();
    final ContentRevision aRev = change.getAfterRevision();

    changeNode.setAttribute(ATT_CHANGE_BEFORE_PATH, bRev != null ? bRev.getFile().getPath() : "");
    changeNode.setAttribute(ATT_CHANGE_AFTER_PATH, aRev != null ? aRev.getFile().getPath() : "");
  }

  private static Change readChange(Element changeNode) throws OutdatedFakeRevisionException {
    String bRev = changeNode.getAttributeValue(ATT_CHANGE_BEFORE_PATH);
    String aRev = changeNode.getAttributeValue(ATT_CHANGE_AFTER_PATH);
    return new Change(StringUtil.isEmpty(bRev) ? null : new FakeRevision(bRev), StringUtil.isEmpty(aRev) ? null : new FakeRevision(aRev));
  }

  static final class OutdatedFakeRevisionException extends Exception {}
}
