/*
 * 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.openapi.components.impl.stores;

import com.intellij.diagnostic.IdeErrorsDialog;
import com.intellij.diagnostic.PluginException;
import com.intellij.ide.plugins.PluginManagerCore;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ex.ApplicationManagerEx;
import com.intellij.openapi.components.*;
import com.intellij.openapi.components.impl.ComponentManagerImpl;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.extensions.PluginId;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.*;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.ArrayUtil;
import com.intellij.util.ReflectionUtil;
import gnu.trove.THashMap;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.*;

@SuppressWarnings({"deprecation"})
public abstract class ComponentStoreImpl implements IComponentStore {
  private static final Logger LOG = Logger.getInstance(ComponentStoreImpl.class);
  private final Map<String, Object> myComponents = Collections.synchronizedMap(new THashMap<String, Object>());
  private final List<SettingsSavingComponent> mySettingsSavingComponents = Collections.synchronizedList(new ArrayList<SettingsSavingComponent>());
  @Nullable private SaveSessionImpl mySession;

  @Nullable
  protected abstract StateStorage getDefaultsStorage();

  @Override
  public void initComponent(@NotNull final Object component, final boolean service) {
    if (component instanceof SettingsSavingComponent) {
      SettingsSavingComponent settingsSavingComponent = (SettingsSavingComponent)component;
      mySettingsSavingComponents.add(settingsSavingComponent);
    }

    boolean isSerializable = component instanceof JDOMExternalizable ||
                             component instanceof PersistentStateComponent;

    if (!isSerializable) return;

    try {
      ApplicationManagerEx.getApplicationEx().runReadAction(new Runnable() {
        @Override
        public void run() {
          if (component instanceof PersistentStateComponent) {
            initPersistentComponent((PersistentStateComponent<?>)component, false);
          }
          else {
            initJdomExternalizable((JDOMExternalizable)component);
          }
        }
      });
    }
    catch (StateStorageException e) {
      throw e;
    }
    catch (Exception e) {
      LOG.error(e);
    }
  }

  @Override
  public boolean isSaving() {
    return mySession != null;
  }


  @Override
  @NotNull
  public SaveSession startSave() throws IOException {
    try {
      final SaveSessionImpl session = createSaveSession();
      try {
        session.commit();
      }
      catch (Throwable e) {
        try {
          session.reset();
        }
        catch (Exception e1_ignored) {
          LOG.info(e1_ignored);
        }

        PluginId pluginId = IdeErrorsDialog.findPluginId(e);
        if (pluginId != null) {
          throw new PluginException(e, pluginId);
        }

        LOG.info(e);
        IOException ioException = new IOException(e.getMessage());
        ioException.initCause(e);
        throw ioException;
      }
      mySession = session;
      return mySession;
    }
    catch (StateStorageException e) {
      LOG.info(e);
      throw new IOException(e.getMessage());
    }
  }

  protected SaveSessionImpl createSaveSession() throws StateStorageException {
    return new SaveSessionImpl();
  }

  public void finishSave(@NotNull final SaveSession saveSession) {
    assert mySession == saveSession;
    mySession.finishSave();
    mySession = null;
  }

  private <T> void commitPersistentComponent(@NotNull final PersistentStateComponent<T> persistentStateComponent,
                                             @NotNull StateStorageManager.ExternalizationSession session) {
    T state = persistentStateComponent.getState();
    if (state != null) {
      Storage[] storageSpecs = getComponentStorageSpecs(persistentStateComponent, StateStorageOperation.WRITE);
      session.setState(storageSpecs, persistentStateComponent, getComponentName(persistentStateComponent), state);
    }
  }

  @Nullable
  private String initJdomExternalizable(@NotNull JDOMExternalizable component) {
    final String componentName = ComponentManagerImpl.getComponentName(component);

    doAddComponent(componentName, component);

    if (optimizeTestLoading()) {
      return componentName;
    }

    loadJdomDefaults(component, componentName);

    StateStorage stateStorage = getStateStorageManager().getOldStorage(component, componentName, StateStorageOperation.READ);

    if (stateStorage == null) return null;
    Element element = getJdomState(component, componentName, stateStorage);

    if (element == null) return null;

    try {
      if (LOG.isDebugEnabled()) {
        LOG.debug("Loading configuration for " + component.getClass());
      }
      component.readExternal(element);
    }
    catch (InvalidDataException e) {
      throw new InvalidComponentDataException(e);
    }

    validateUnusedMacros(componentName, true);

    return componentName;
  }

  private void doAddComponent(String componentName, Object component) {
    Object existing = myComponents.get(componentName);
    if (existing != null && existing != component) {
      LOG.error("Conflicting component name '" + componentName + "': " + existing.getClass() + " and " + component.getClass());
    }
    myComponents.put(componentName, component);
  }

  private void loadJdomDefaults(@NotNull final Object component, final String componentName) {
    try {
      StateStorage defaultsStorage = getDefaultsStorage();
      if (defaultsStorage == null) return;

      Element defaultState = getJdomState(component, componentName, defaultsStorage);
      if (defaultState == null) return;

      ((JDOMExternalizable)component).readExternal(defaultState);
    }
    catch (Exception e) {
      LOG.error("Cannot load defaults for " + component.getClass(), e);
    }
  }

  @Nullable
  private static Element getJdomState(final Object component, final String componentName, @NotNull final StateStorage defaultsStorage)
      throws StateStorageException {
    ComponentRoamingManager roamingManager = ComponentRoamingManager.getInstance();
    if (component instanceof RoamingTypeDisabled) {
      roamingManager.setRoamingType(componentName, RoamingType.DISABLED);
    }
    return defaultsStorage.getState(component, componentName, Element.class, null);
  }

  @Nullable
  protected Project getProject() {
    return null;
  }

  private void validateUnusedMacros(@Nullable final String componentName, final boolean service) {
    final Project project = getProject();
    if (project == null) return;

    if (!ApplicationManager.getApplication().isHeadlessEnvironment() && !ApplicationManager.getApplication().isUnitTestMode()) {
      if (service && componentName != null && project.isInitialized()) {
        final TrackingPathMacroSubstitutor substitutor = getStateStorageManager().getMacroSubstitutor();
        if (substitutor != null) {
          StorageUtil.notifyUnknownMacros(substitutor, project, componentName);
        }
      }
    }

  }

  private <T> String initPersistentComponent(@NotNull final PersistentStateComponent<T> component, final boolean reloadData) {
    State spec = getStateSpec(component);
    final String name = spec.name();
    ComponentRoamingManager.getInstance().setRoamingType(name, spec.roamingType());

    doAddComponent(name, component);
    if (optimizeTestLoading()) return name;

    Class<T> stateClass = getComponentStateClass(component);

    T state = null;
    //todo: defaults merging

    final StateStorage defaultsStorage = getDefaultsStorage();
    if (defaultsStorage != null) {
      state = defaultsStorage.getState(component, name, stateClass, null);
    }

    Storage[] storageSpecs = getComponentStorageSpecs(component, StateStorageOperation.READ);
    for (Storage storageSpec : storageSpecs) {
      StateStorage stateStorage = getStateStorageManager().getStateStorage(storageSpec);
      if (stateStorage != null && stateStorage.hasState(component, name, stateClass, reloadData)) {
        state = stateStorage.getState(component, name, stateClass, state);
      }
    }

    if (state != null) {
      component.loadState(state);
    }

    validateUnusedMacros(name, true);

    return name;
  }

  @NotNull
  private static <T> Class<T> getComponentStateClass(@NotNull final PersistentStateComponent<T> persistentStateComponent) {
    final Class persistentStateComponentClass = PersistentStateComponent.class;

    Class componentClass = persistentStateComponent.getClass();

    nextSuperClass:
    while (true) {
      for (Class anInterface : componentClass.getInterfaces()) {
        if (anInterface.equals(persistentStateComponentClass)) {
          break nextSuperClass;
        }
      }

      componentClass = componentClass.getSuperclass();
    }

    final Type type = ReflectionUtil.resolveVariable(persistentStateComponentClass.getTypeParameters()[0], componentClass);
    assert type != null;
    //noinspection unchecked
    return (Class<T>)ReflectionUtil.getRawType(type);
  }

  public static String getComponentName(@NotNull final PersistentStateComponent<?> persistentStateComponent) {
    return getStateSpec(persistentStateComponent).name();
  }

  @NotNull
  private static <T> State getStateSpec(@NotNull final PersistentStateComponent<T> persistentStateComponent) {
    final Class<? extends PersistentStateComponent> aClass = persistentStateComponent.getClass();
    final State stateSpec = aClass.getAnnotation(State.class);
    if (stateSpec == null) {
      final PluginId pluginId = PluginManagerCore.getPluginByClassName(aClass.getName());
      if (pluginId != null) {
        throw new PluginException("No @State annotation found in " + aClass, pluginId);
      }
      throw new RuntimeException("No @State annotation found in " + aClass);
    }
    return stateSpec;
  }

  @NotNull
  protected <T> Storage[] getComponentStorageSpecs(@NotNull final PersistentStateComponent<T> persistentStateComponent,
                                                   final StateStorageOperation operation) throws StateStorageException {
    final State stateSpec = getStateSpec(persistentStateComponent);
    final Storage[] storages = stateSpec.storages();
    if (storages.length == 1) {
      return storages;
    }
    assert storages.length > 0;

    final Class<? extends StateStorageChooser> storageChooserClass = stateSpec.storageChooser();
    if (storageChooserClass == StateStorageChooser.class) {
      StateStorageChooser<PersistentStateComponent<?>> defaultStateStorageChooser = getDefaultStateStorageChooser();
      assert defaultStateStorageChooser != null : "State chooser not specified for: " + persistentStateComponent.getClass();
      return defaultStateStorageChooser.selectStorages(storages, persistentStateComponent, operation);
    }
    else if (storageChooserClass == LastStorageChooserForWrite.class) {
      return LastStorageChooserForWrite.INSTANCE.selectStorages(storages, persistentStateComponent, operation);
    }
    else {
      try {
        @SuppressWarnings("unchecked")
        StateStorageChooser<PersistentStateComponent<T>> storageChooser = ReflectionUtil.newInstance(storageChooserClass);
        return storageChooser.selectStorages(storages, persistentStateComponent, operation);
      }
      catch (RuntimeException e) {
        throw new StateStorageException(e);
      }
    }
  }

  protected boolean optimizeTestLoading() {
    return false;
  }

  @Nullable
  protected StateStorageChooser<PersistentStateComponent<?>> getDefaultStateStorageChooser() {
    return null;
  }

  protected class SaveSessionImpl implements SaveSession {
    protected StateStorageManager.SaveSession myStorageManagerSaveSession;

    public SaveSessionImpl() {
      ShutDownTracker.getInstance().registerStopperThread(Thread.currentThread());
    }

    @NotNull
    @Override
    public List<File> getAllStorageFilesToSave(final boolean includingSubStructures) throws IOException {
      try {
        return myStorageManagerSaveSession.getAllStorageFilesToSave();
      }
      catch (StateStorageException e) {
        throw new IOException(e.getMessage());
      }
    }

    @NotNull
    @Override
    public SaveSession save() throws IOException {
      try {
        final SettingsSavingComponent[] settingsComponents =
            mySettingsSavingComponents.toArray(new SettingsSavingComponent[mySettingsSavingComponents.size()]);

        for (SettingsSavingComponent settingsSavingComponent : settingsComponents) {
          try {
            settingsSavingComponent.save();
          }
          catch (StateStorageException e) {
            LOG.info(e);
            throw new IOException(e.getMessage());
          }
          catch (Exception e) {
            LOG.error(e);
          }
        }

        myStorageManagerSaveSession.save();
      }
      catch (StateStorageException e) {
        LOG.info(e);
        throw new IOException(e.getMessage(), e);
      }

      return this;
    }

    @Override
    public void finishSave() {
      try {
        getStateStorageManager().finishSave(myStorageManagerSaveSession);
        myStorageManagerSaveSession = null;
      }
      finally {
        ShutDownTracker.getInstance().unregisterStopperThread(Thread.currentThread());
        mySession = null;
      }
    }

    @Override
    public void reset() {
      try {
        getStateStorageManager().reset();
        myStorageManagerSaveSession = null;
      }
      finally {
        ShutDownTracker.getInstance().unregisterStopperThread(Thread.currentThread());
        mySession = null;
      }
    }

    protected void commit() throws StateStorageException {
      final StateStorageManager storageManager = getStateStorageManager();
      final StateStorageManager.ExternalizationSession session = storageManager.startExternalization();

      String[] names = ArrayUtil.toStringArray(myComponents.keySet());
      Arrays.sort(names);
      for (String name : names) {
        Object component = myComponents.get(name);
        if (component instanceof PersistentStateComponent) {
          commitPersistentComponent((PersistentStateComponent<?>)component, session);
        }
        else if (component instanceof JDOMExternalizable) {
          session.setStateInOldStorage(component, ComponentManagerImpl.getComponentName(component), component);
        }
      }
      myStorageManagerSaveSession = storageManager.startSave(session);
    }

    @Override
    @Nullable
    public Set<String> analyzeExternalChanges(@NotNull final Set<Pair<VirtualFile, StateStorage>> changedFiles) {
      return myStorageManagerSaveSession.analyzeExternalChanges(changedFiles);
    }

    @NotNull
    @Override
    public List<File> getAllStorageFiles(final boolean includingSubStructures) {
      return myStorageManagerSaveSession.getAllStorageFiles();
    }
  }

  @Override
  public boolean isReloadPossible(@NotNull final Set<String> componentNames) {
    for (String componentName : componentNames) {
      final Object component = myComponents.get(componentName);
      if (component != null && (!(component instanceof PersistentStateComponent) || !getStateSpec((PersistentStateComponent<?>)component).reloadable())) {
        return false;
      }
    }

    return true;
  }

  @Override
  public void reinitComponents(@NotNull final Set<String> componentNames, final boolean reloadData) {
    for (String componentName : componentNames) {
      final PersistentStateComponent component = (PersistentStateComponent)myComponents.get(componentName);
      if (component != null) {
        initPersistentComponent(component, reloadData);
      }
    }
  }

  protected void doReload(final Set<Pair<VirtualFile, StateStorage>> changedFiles, @NotNull final Set<String> componentNames)
      throws StateStorageException {
    for (Pair<VirtualFile, StateStorage> pair : changedFiles) {
      assert pair != null;
      final StateStorage storage = pair.second;
      assert storage != null : "Null storage for: " + pair.first;
      storage.reload(componentNames);
    }
  }
}
