/*
 * Copyright 2003-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 jetbrains.mps.idea.core.actions;

import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.LangDataKeys;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiElement;
import jetbrains.mps.extapi.persistence.SourceRoot;
import jetbrains.mps.ide.project.ProjectHelper;
import jetbrains.mps.ide.vfs.VirtualFileUtils;
import jetbrains.mps.idea.core.project.module.ModuleMPSSupport;
import jetbrains.mps.persistence.DefaultModelRoot;
import jetbrains.mps.project.MPSProject;

import javax.swing.Icon;

public abstract class NewModelActionBase extends AnAction {
  protected Project myProject;
  protected DefaultModelRoot myModelRoot;
  protected SourceRoot mySourceRoot;
  protected String myModelPrefix;
//  protected DataSourceFactoryFromName myDataSourceFactory;

  protected NewModelActionBase(String text, String description, Icon icon) {
    super(text, description, icon);
  }

  @Override
  public void update(AnActionEvent e) {
    updateFields(e);

    boolean enabled = isEnabled(e);
    e.getPresentation().setVisible(enabled);
    e.getPresentation().setEnabled(enabled);
  }

  private void updateFields(AnActionEvent e) {
    myProject = e.getData(PlatformDataKeys.PROJECT);
    if (myProject == null) {
      return;
    }
    myModelRoot = null;
    myModelPrefix = null;
    final Module module = e.getData(LangDataKeys.MODULE);
    final VirtualFile[] vFiles = e.getData(PlatformDataKeys.VIRTUAL_FILE_ARRAY);
    if (module == null || vFiles == null || vFiles.length != 1 || !vFiles[0].isDirectory()) {
      return;
    }
    final VirtualFile targetDir = vFiles[0];

    final ModuleMPSSupport mpsFacade = ModuleMPSSupport.getInstance();
    if (mpsFacade == null || !mpsFacade.isMPSEnabled(module)) {
      return;
    }

    String url = targetDir.getUrl();
    if (!LocalFileSystem.PROTOCOL.equals(VirtualFileManager.extractProtocol(url))) {
      return;
    }

    final MPSProject mpsProject = ProjectHelper.fromIdeaProject(module.getProject());
    assert mpsProject != null;
    mpsProject.getModelAccess().runReadAction(() -> {
      Pair<DefaultModelRoot, SourceRoot> location = mpsFacade.getModelRoot(module, targetDir);
      if (location == null) {
        return;
      }
      myModelRoot = location.first;
      mySourceRoot = location.second;
      myModelPrefix = packagePrefix(mySourceRoot, targetDir);
//      myDataSourceFactory = createDataSourceFactory(targetDir);
    });
  }
  
  private String packagePrefix(SourceRoot sourceRoot, VirtualFile dir) {
    final VirtualFile sourceRootPath = VirtualFileUtils.getProjectVirtualFile(sourceRoot.getAbsolutePath());
    assert sourceRootPath != null : "Can't find root directory for model";
    String prefix = VfsUtilCore.getRelativePath(dir, sourceRootPath);
    assert prefix != null : "Can't find relative path between input path and root path for model";
    prefix = prefix.replace('/', '.').replace('\\', '.');
    // in case in the future idea leaves some dangling slashes
    while (prefix.startsWith(".")) {
      prefix = prefix.substring(1);
    }
    while (prefix.endsWith(".")) {
      prefix = prefix.substring(0, prefix.length());
    }
    return prefix;
  }

//  protected abstract DataSourceFactoryFromName createDataSourceFactory(VirtualFile targetFile);

  protected boolean isEnabled(AnActionEvent e) {
    PsiElement psiElement = e.getData(LangDataKeys.PSI_ELEMENT);
    if (psiElement == null || !(psiElement instanceof PsiDirectory)) {
      return false;
    }

    Module module = e.getData(LangDataKeys.MODULE);
    return module != null && mySourceRoot != null && myModelRoot != null && myProject != null;
  }
}
