package jetbrains.mps.vcs.diff.merge;

/*Generated by MPS */

import jetbrains.mps.annotations.GeneratedClass;
import jetbrains.mps.smodel.EditableModelDescriptor;
import jetbrains.mps.persistence.PersistenceVersionAware;
import org.jetbrains.mps.openapi.model.EditableSModel;
import jetbrains.mps.extapi.model.GeneratableSModel;
import org.jetbrains.mps.openapi.model.SModelReference;
import org.jetbrains.mps.openapi.persistence.NullDataSource;
import org.jetbrains.mps.openapi.model.SModel;
import jetbrains.mps.smodel.CopyUtil;
import jetbrains.mps.extapi.model.SModelBase;
import jetbrains.mps.smodel.ModelLoadResult;
import jetbrains.mps.smodel.loading.ModelLoadingState;
import org.jetbrains.annotations.NotNull;
import jetbrains.mps.smodel.DefaultSModel;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.mps.openapi.persistence.ModelFactory;
import org.jetbrains.mps.openapi.persistence.PersistenceFacade;

/**
 * Merge model has to be EditableSModel for now (there's otherwise dubious use of isChanged status),
 * however, rest of the EditableSModel API is superfluous for the merge model.
 */
@GeneratedClass(node = "r:e9c4e128-4808-4224-a92b-dbeed02eb860(jetbrains.mps.vcs.diff.merge)/1549936565245931290", model = "r:e9c4e128-4808-4224-a92b-dbeed02eb860(jetbrains.mps.vcs.diff.merge)")
public final class MergeTemporaryModel extends EditableModelDescriptor implements PersistenceVersionAware, EditableSModel, GeneratableSModel {
  private final boolean myReadOnly;

  public MergeTemporaryModel(SModelReference modelRef, boolean readonly) {
    super(modelRef, new NullDataSource());
    myReadOnly = readonly;
  }

  public static MergeTemporaryModel writableCloneOf(SModel model) {
    return cloneDataInto(new MergeTemporaryModel(model.getReference(), false), model);
  }

  public static MergeTemporaryModel readonlyCloneOf(SModel model) {
    return cloneDataInto(new MergeTemporaryModel(model.getReference(), true), model);
  }

  private static MergeTemporaryModel cloneDataInto(MergeTemporaryModel rv, SModel origin) {
    // TODO generalize merge for any SModel
    jetbrains.mps.smodel.SModel resModel = CopyUtil.copyModel(((SModelBase) origin).getSModel());
    rv.replace(new ModelLoadResult<jetbrains.mps.smodel.SModel>(resModel, ModelLoadingState.FULLY_LOADED));
    return rv;
  }

  @NotNull
  protected ModelLoadResult<jetbrains.mps.smodel.SModel> createModel() {
    // XXX why not UnsupportedOperationException? Generally, we shall never get here (well, except of unloaded model)
    return new ModelLoadResult<jetbrains.mps.smodel.SModel>(new jetbrains.mps.smodel.SModel(getReference()), ModelLoadingState.FULLY_LOADED);
  }

  /*package*/ void setSModelInternal(jetbrains.mps.smodel.SModel model) {
    assert model == null || getReference().equals(model.getReference());
    replace(new ModelLoadResult<jetbrains.mps.smodel.SModel>(model, (model == null ? ModelLoadingState.NOT_LOADED : ModelLoadingState.FULLY_LOADED)));
  }

  @Override
  public void save() {
    // no-op
  }

  @Override
  public void rename(String newModelName, boolean changeFile) {
    throw new UnsupportedOperationException();
  }

  @Override
  public boolean isReadOnly() {
    return myReadOnly;
  }

  @Override
  public void reloadFromSource() {
    throw new UnsupportedOperationException();
  }

  @Override
  public void updateTimestamp() {
    // no-op
  }
  @Override
  public boolean needsReloading() {
    return false;
  }

  public void setPersistenceVersion(int version) {
    if (getModelData() instanceof DefaultSModel) {
      ((DefaultSModel) getModelData()).getSModelHeader().setPersistenceVersion(version);
    }
  }
  public int getPersistenceVersion() {
    if (getModelData() instanceof DefaultSModel) {
      return ((DefaultSModel) getModelData()).getSModelHeader().getPersistenceVersion();
    }
    return -1;
  }

  @Nullable
  public ModelFactory getModelFactory() {
    // in fact, shall derive persistence from models being merged, however, so far we've got merge for default/xml persistence only, thus it's ok to hardcode specific factory
    // XXX is there any use of the method during merge? Perhaps, could go with plain 'null'?
    return PersistenceFacade.getInstance().getDefaultModelFactory();
  }

  @Override
  public boolean isGeneratable() {
    return false;
  }
  @Override
  public boolean isGenerateIntoModelFolder() {
    return false;
  }
  @Override
  public void setGenerateIntoModelFolder(boolean b) {
  }
  @Override
  public String getModelHash() {
    return null;
  }
  @Override
  public void setDoNotGenerate(boolean b) {
    if (getModelData() instanceof DefaultSModel) {
      ((DefaultSModel) getModelData()).getSModelHeader().setOptionalProperty(GeneratableSModel.DO_NOT_GENERATE, Boolean.toString(b));
    }
  }
  @Override
  public boolean isDoNotGenerate() {
    if (getModelData() instanceof DefaultSModel) {
      return Boolean.parseBoolean(((DefaultSModel) getModelData()).getSModelHeader().getOptionalProperty(GeneratableSModel.DO_NOT_GENERATE));
    }
    return false;
  }
}
