/*
 * Copyright 2000-2014 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.profile;

import com.intellij.openapi.Disposable;
import com.intellij.openapi.components.StateSplitter;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.*;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.packageDependencies.DependencyValidationManager;
import com.intellij.psi.search.scope.packageSet.NamedScopesHolder;
import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.text.UniqueNameGenerator;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.*;

/**
 * User: anna
 * Date: 30-Nov-2005
 */
public abstract class DefaultProjectProfileManager extends ProjectProfileManager implements JDOMExternalizable {
  protected static final Logger LOG = Logger.getInstance("#com.intellij.profile.DefaultProjectProfileManager");

  @NonNls protected static final String PROFILES = "profiles";
  @NonNls public static final String SCOPES = "scopes";
  @NonNls protected static final String SCOPE = "scope";
  @NonNls public static final String PROFILE = "profile";
  @NonNls protected static final String NAME = "name";


  private static final String VERSION = "1.0";

  @NotNull
  protected final Project myProject;

  /** This field is used for serialization. Do not rename it or make access weaker */
  public String PROJECT_PROFILE;
  /** This field is used for serialization. Do not rename it or make access weaker */
  public boolean USE_PROJECT_PROFILE = true;

  private final ApplicationProfileManager myApplicationProfileManager;

  private final Map<String, Profile> myProfiles = new HashMap<String, Profile>();
  protected final DependencyValidationManager myHolder;
  private final List<ProfileChangeAdapter> myProfilesListener = ContainerUtil.createLockFreeCopyOnWriteList();
  @NonNls private static final String PROJECT_DEFAULT_PROFILE_NAME = "Project Default";

  public DefaultProjectProfileManager(@NotNull final Project project,
                                      @NotNull ApplicationProfileManager applicationProfileManager,
                                      @NotNull DependencyValidationManager holder) {
    myProject = project;
    myHolder = holder;
    myApplicationProfileManager = applicationProfileManager;
  }

  @NotNull
  public Project getProject() {
    return myProject;
  }

  @Override
  public synchronized Profile getProfile(@NotNull String name, boolean returnRootProfileIfNamedIsAbsent) {
    return myProfiles.containsKey(name) ? myProfiles.get(name) : myApplicationProfileManager.getProfile(name, returnRootProfileIfNamedIsAbsent);
  }

  @Override
  public synchronized void updateProfile(@NotNull Profile profile) {
    myProfiles.put(profile.getName(), profile);
    for (ProfileChangeAdapter profileChangeAdapter : myProfilesListener) {
      profileChangeAdapter.profileChanged(profile);
    }
  }

  @Override
  public synchronized void readExternal(Element element) throws InvalidDataException {
    myProfiles.clear();
    DefaultJDOMExternalizer.readExternal(this, element);
    final Element profilesElement = element.getChild(PROFILES);
    if (profilesElement != null) {
      for (Object o : profilesElement.getChildren(PROFILE)) {
        final Profile profile = myApplicationProfileManager.createProfile();
        profile.setProfileManager(this);
        profile.readExternal((Element)o);
        final String name = profile.getName();
        if (myApplicationProfileManager.getProfile(name) != null) { //override ide profile
          // myApplicationProfileManager.deleteProfile(name);
        }
        myProfiles.put(name, profile);
      }
    }
    if (element.getChild("version") == null || !Comparing.strEqual(element.getChild("version").getAttributeValue("value"), VERSION)) {
      boolean toConvert = true;
      for (Object o : element.getChildren("option")) {
        if (Comparing.strEqual(((Element)o).getAttributeValue("name"), "USE_PROJECT_LEVEL_SETTINGS")) {
          toConvert = Boolean.parseBoolean(((Element)o).getAttributeValue("value"));
          break;
        }
      }
      if (toConvert) {
        convert(element);
      }
    }
  }

  protected void convert(Element element) throws InvalidDataException {
  }

  @Override
  public synchronized void writeExternal(Element element) throws WriteExternalException {

    final List<String> sortedProfiles = new ArrayList<String>(myProfiles.keySet());
    Collections.sort(sortedProfiles);
    Element profiles = null;
    for (String profile : sortedProfiles) {
      final Profile projectProfile = myProfiles.get(profile);
      if (projectProfile != null) {
        final Element profileElement = new Element(PROFILE);
        projectProfile.writeExternal(profileElement);
        boolean hasSmthToSave = sortedProfiles.size() > 1 || isDefaultProfileUsed();
        if (!hasSmthToSave) {
          for (Object child : profileElement.getChildren()) {
            if (!((Element)child).getName().equals("option")) {
              hasSmthToSave = true;
              break;
            }
          }
        }
        if (!hasSmthToSave) continue;

        if (profiles == null) {
          profiles = new Element(PROFILES);
          element.addContent(profiles);
        }

        profiles.addContent(profileElement);
      }
    }

    if (profiles != null || isDefaultProfileUsed()) {
      DefaultJDOMExternalizer.writeExternal(this, element);
      final Element version = new Element("version");
      version.setAttribute("value", VERSION);
      element.addContent(version);
    }
  }

  private boolean isDefaultProfileUsed() {
    return PROJECT_PROFILE != null && !Comparing.strEqual(PROJECT_PROFILE, PROJECT_DEFAULT_PROFILE_NAME);
  }

  @NotNull
  @Override
  public NamedScopesHolder getScopesManager() {
    return myHolder;
  }

  @NotNull
  @Override
  public synchronized Collection<Profile> getProfiles() {
    getProjectProfileImpl();
    return myProfiles.values();
  }

  @NotNull
  @Override
  public synchronized String[] getAvailableProfileNames() {
    return ArrayUtil.toStringArray(myProfiles.keySet());
  }

  @Override
  public synchronized void deleteProfile(String name) {
    myProfiles.remove(name);
  }

  @Override
  public synchronized String getProjectProfile() {
    return PROJECT_PROFILE;
  }

  @Override
  public synchronized void setProjectProfile(@Nullable final String newProfile) {
    final String oldProfile = PROJECT_PROFILE;
    PROJECT_PROFILE = newProfile;
    USE_PROJECT_PROFILE = newProfile != null;
    if (oldProfile != null) {
      for (ProfileChangeAdapter adapter : myProfilesListener) {
        adapter.profileActivated(getProfile(oldProfile), newProfile != null ?  getProfile(newProfile) : null);
      }
    }
  }

  @NotNull
  public synchronized Profile getProjectProfileImpl(){
    if (!USE_PROJECT_PROFILE) return myApplicationProfileManager.getRootProfile();
    if (PROJECT_PROFILE == null || myProfiles.isEmpty()){
      setProjectProfile(PROJECT_DEFAULT_PROFILE_NAME);
      final Profile projectProfile = myApplicationProfileManager.createProfile();
      projectProfile.copyFrom(myApplicationProfileManager.getRootProfile());
      projectProfile.setLocal(false);
      projectProfile.setName(PROJECT_DEFAULT_PROFILE_NAME);
      myProfiles.put(PROJECT_DEFAULT_PROFILE_NAME, projectProfile);
    }
    else if (!myProfiles.containsKey(PROJECT_PROFILE)){
      final String projectProfileAttempt = myProfiles.keySet().iterator().next();
      setProjectProfile(projectProfileAttempt);
    }
    final Profile profile = myProfiles.get(PROJECT_PROFILE);
    profile.setProfileManager(this);
    return profile;
  }

  public void addProfilesListener(@NotNull final ProfileChangeAdapter profilesListener, @NotNull Disposable parent) {
    myProfilesListener.add(profilesListener);
    Disposer.register(parent, new Disposable() {
      @Override
      public void dispose() {
        myProfilesListener.remove(profilesListener);
      }
    });
  }

  public void removeProfilesListener(@NotNull ProfileChangeAdapter profilesListener) {
    myProfilesListener.remove(profilesListener);
  }

  public static class ProfileStateSplitter implements StateSplitter {

    @Override
    public List<Pair<Element, String>> splitState(final Element e) {
      final UniqueNameGenerator generator = new UniqueNameGenerator();
      List<Pair<Element, String>> result = new ArrayList<Pair<Element, String>>();

      final Element[] elements = JDOMUtil.getElements(e);
      for (Element element : elements) {
        if (element.getName().equals("profiles")) {
          element.detach();

          final Element[] profiles = JDOMUtil.getElements(element);
          for (Element profile : profiles) {
            String profileName = null;

            final Element[] options = JDOMUtil.getElements(profile);
            for (Element option : options) {
              if (option.getName().equals("option") && option.getAttributeValue("name").equals("myName")) {
                profileName = option.getAttributeValue("value");
              }
            }

            assert profileName != null;

            final String name = generator.generateUniqueName(FileUtil.sanitizeFileName(profileName)) + ".xml";
            result.add(Pair.create(profile, name));
          }
        }
      }


      if (!e.getContent().isEmpty()) result.add(Pair.create(e, generator.generateUniqueName("profiles_settings") + ".xml"));

      return result;
    }

    @Override
    public void mergeStatesInto(final Element target, final Element[] elements) {
      Element profiles = new Element("profiles");
      target.addContent(profiles);

        for (Element element : elements) {
        if (element.getName().equals("profile")) {
          element.detach();
          profiles.addContent(element);
        }
        else {
          final Element[] states = JDOMUtil.getElements(element);
          for (Element state : states) {
            state.detach();
            target.addContent(state);
          }
        }
      }
    }
  }

  protected void fireProfilesInitialized() {
    for (ProfileChangeAdapter profileChangeAdapter : myProfilesListener) {
      profileChangeAdapter.profilesInitialized();
    }
  }
  protected void fireProfilesShutdown() {
    for (ProfileChangeAdapter profileChangeAdapter : myProfilesListener) {
      profileChangeAdapter.profilesShutdown();
    }
  }
}
