package jetbrains.mps.lang.script.pluginSolution.plugin;

/*Generated by MPS */

import java.util.List;
import org.jetbrains.mps.openapi.model.SNode;
import org.jetbrains.mps.openapi.module.SearchScope;
import jetbrains.mps.project.MPSProject;
import java.util.ArrayList;
import jetbrains.mps.lang.script.runtime.RefactoringScript;
import jetbrains.mps.plugins.projectplugins.ProjectPluginManager;
import org.jetbrains.mps.openapi.module.SModule;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SNodeOperations;
import jetbrains.mps.smodel.Language;
import jetbrains.mps.smodel.language.LanguageRuntime;
import jetbrains.mps.smodel.language.LanguageRegistry;
import jetbrains.mps.lang.script.runtime.ScriptAspectDescriptor;
import org.jetbrains.mps.openapi.model.SNodeReference;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SPropertyOperations;
import org.jetbrains.mps.openapi.model.SModel;
import jetbrains.mps.project.Project;
import java.util.Collections;
import java.util.Set;
import jetbrains.mps.internal.collections.runtime.SetSequence;
import java.util.HashSet;
import jetbrains.mps.internal.collections.runtime.Sequence;
import jetbrains.mps.ide.findusages.model.scopes.ModelsScope;
import org.jetbrains.mps.openapi.model.EditableSModel;
import jetbrains.mps.smodel.SModelStereotype;
import org.jetbrains.mps.openapi.language.SProperty;
import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory;

/**
 * 
 * @deprecated AbstractHelper no one sub-classes, ORLY? Mostly legacy code for migration scripts executed as nodes. Scope manipulation, if vital, could move closer to uses.
 */
@Deprecated(since = "3.3", forRemoval = true)
public abstract class AbstractMigrationScriptHelper {
  public static void doRunScripts(List<SNode> scriptNodes, SearchScope scope, MPSProject context) {
    ArrayList<RefactoringScript> scripts = new ArrayList<RefactoringScript>();
    for (SNode n : scriptNodes) {
      RefactoringScript ms = toExecutable(n, context);
      if (ms != null) {
        scripts.add(ms);
      }
    }
    context.getProject().getComponent(ProjectPluginManager.class).getTool(MigrationScriptsTool_Tool.class).startMigration(scripts, scope);
  }

  public static RefactoringScript toExecutable(SNode scriptNode, MPSProject contextProject) {
    SModule module = SNodeOperations.getModel(scriptNode).getModule();
    if (!(module instanceof Language)) {
      return null;
    }
    LanguageRuntime lr = contextProject.getComponent(LanguageRegistry.class).getLanguage((Language) module);
    ScriptAspectDescriptor scriptAspect = (lr == null ? null : lr.getAspect(ScriptAspectDescriptor.class));
    if (scriptAspect == null) {
      return null;
    }
    final SNodeReference scriptNodeRef = SNodeOperations.getPointer(scriptNode);
    for (RefactoringScript rs : scriptAspect.getRefactoringScripts()) {
      if (scriptNodeRef.equals(rs.getScriptNode())) {
        return rs;
      }
    }
    // try name match if none matched by node reference
    for (RefactoringScript rs : scriptAspect.getRefactoringScripts()) {
      if (rs.getName().equals(SPropertyOperations.getString(scriptNode, PROPS.title$6bZx))) {
        return rs;
      }
    }

    return null;
  }

  public static SearchScope createMigrationScope(Iterable<SModule> selectedModules, Iterable<SModel> selectedModels) {
    return createMigrationScopeInternal(selectedModules, selectedModels);
  }

  public static SearchScope createMigrationScope(Project project) {
    return createMigrationScopeInternal(project.getProjectModulesWithGenerators(), (Iterable<SModel>) Collections.<SModel>emptySet());
  }

  private static SearchScope createMigrationScopeInternal(Iterable<SModule> modules, Iterable<SModel> models) {
    Set<SModel> result = SetSequence.fromSet(new HashSet<SModel>());
    SetSequence.fromSet(result).addSequence(Sequence.fromIterable(models).where((it) -> includeModel(it)));
    SetSequence.fromSet(result).addSequence(Sequence.fromIterable(modules).where((it) -> !(it.isReadOnly())).translate((it) -> it.getModels()).where((it) -> includeModel(it)));
    return new ModelsScope(result);
  }
  private static boolean includeModel(SModel model) {
    if (!(model instanceof EditableSModel)) {
      return false;
    }
    if (model.isReadOnly()) {
      return false;
    }
    if (SModelStereotype.isStubModel(model)) {
      return false;
    }
    return true;
  }

  private static final class PROPS {
    /*package*/ static final SProperty title$6bZx = MetaAdapterFactory.getProperty(0xeddeefac2d64437L, 0xbc2cde50fd4ce470L, 0x11225e9072dL, 0x11225f2354aL, "title");
  }
}
