package com.intellij.updater;

import java.io.*;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.nio.channels.OverlappingFileLockException;
import java.util.Map;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;

public abstract class PatchAction {
  protected String myPath;
  protected long myChecksum;
  private boolean isCritical;
  private boolean isOptional;

  public PatchAction(String path, long checksum) {
    myPath = path;
    myChecksum = checksum;
  }

  public PatchAction(DataInputStream in) throws IOException {
    myPath = in.readUTF();
    myChecksum = in.readLong();
    isCritical = in.readBoolean();
    isOptional = in.readBoolean();
  }

  public void write(DataOutputStream out) throws IOException {
    out.writeUTF(myPath);
    out.writeLong(myChecksum);
    out.writeBoolean(isCritical);
    out.writeBoolean(isOptional);
  }

  public String getPath() {
    return myPath;
  }

  protected static void writeExecutableFlag(OutputStream out, File file) throws IOException {
    out.write(file.canExecute() ? 1 : 0);
  }

  protected static boolean readExecutableFlag(InputStream in) throws IOException {
    return in.read() == 1;
  }

  public boolean calculate(File olderDir, File newerDir) throws IOException {
    return doCalculate(getFile(olderDir), getFile(newerDir));
  }

  protected boolean doCalculate(File olderFile, File newerFile) throws IOException {
    return true;
  }

  public void buildPatchFile(File olderDir, File newerDir, ZipOutputStream patchOutput) throws IOException {
    doBuildPatchFile(getFile(olderDir), getFile(newerDir), patchOutput);
  }

  protected abstract void doBuildPatchFile(File olderFile, File newerFile, ZipOutputStream patchOutput) throws IOException;

  public boolean shouldApply(File toDir, Map<String, ValidationResult.Option> options) {
    ValidationResult.Option option = options.get(myPath);
    if (option == ValidationResult.Option.KEEP || option == ValidationResult.Option.IGNORE) return false;
    return shouldApplyOn(getFile(toDir));
  }

  protected boolean shouldApplyOn(File toFile) {
    return true;
  }

  public ValidationResult validate(File toDir) throws IOException {
    return doValidate(getFile(toDir));
  }

  protected abstract ValidationResult doValidate(final File toFile) throws IOException;

  protected ValidationResult doValidateAccess(File toFile, ValidationResult.Action action) {
    if (!toFile.exists()) return null;
    if (toFile.isDirectory()) return null;
    if (toFile.canRead() && toFile.canWrite() && isWritable(toFile)) return null;
    return new ValidationResult(ValidationResult.Kind.ERROR,
                                myPath,
                                action,
                                ValidationResult.ACCESS_DENIED_MESSAGE,
                                ValidationResult.Option.IGNORE);
  }

  private boolean isWritable(File toFile) {
    try {
      FileOutputStream s = new FileOutputStream(toFile, true);
      FileChannel ch = s.getChannel();
      try {
        FileLock lock = ch.tryLock();
        if (lock == null) return false;
        lock.release();
      }
      finally {
        ch.close();
        s.close();
      }
      return true;
    }
    catch (OverlappingFileLockException e) {
      Runner.printStackTrace(e);
      return false;
    }
    catch (IOException e) {
      Runner.printStackTrace(e);
      return false;
    }
  }

  protected ValidationResult doValidateNotChanged(File toFile, ValidationResult.Kind kind, ValidationResult.Action action)
    throws IOException {
    if (toFile.exists()) {
      if (isModified(toFile)) {
        return new ValidationResult(kind,
                                    myPath,
                                    action,
                                    ValidationResult.MODIFIED_MESSAGE,
                                    ValidationResult.Option.IGNORE);
      }
    }
    else if (!isOptional) {
      return new ValidationResult(kind,
                                  myPath,
                                  action,
                                  ValidationResult.ABSENT_MESSAGE,
                                  ValidationResult.Option.IGNORE);
    }
    return null;
  }

  protected boolean isModified(File toFile) throws IOException {
    return myChecksum != Digester.digestFile(toFile);
  }

  public void apply(ZipFile patchFile, File toDir) throws IOException {
    doApply(patchFile, getFile(toDir));
  }

  protected abstract void doApply(ZipFile patchFile, File toFile) throws IOException;

  public void backup(File toDir, File backupDir) throws IOException {
    doBackup(getFile(toDir), getFile(backupDir));
  }

  protected abstract void doBackup(File toFile, File backupFile) throws IOException;

  public void revert(File toDir, File backupDir) throws IOException {
    doRevert(getFile(toDir), getFile(backupDir));
  }

  protected abstract void doRevert(File toFile, File backupFile) throws IOException;

  private File getFile(File baseDir) {
    return new File(baseDir, myPath);
  }

  public boolean isCritical() {
    return isCritical;
  }

  public void setCritical(boolean critical) {
    isCritical = critical;
  }

  public boolean isOptional() {
    return isOptional;
  }

  public void setOptional(boolean optional) {
    isOptional = optional;
  }

  @Override
  public String toString() {
    return getClass().getSimpleName() + "(" + myPath + ", " + myChecksum + ")";
  }

  @Override
  public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;

    PatchAction that = (PatchAction)o;

    if (isCritical != that.isCritical) return false;
    if (isOptional != that.isOptional) return false;
    if (myChecksum != that.myChecksum) return false;
    if (myPath != null ? !myPath.equals(that.myPath) : that.myPath != null) return false;

    return true;
  }

  @Override
  public int hashCode() {
    int result = myPath != null ? myPath.hashCode() : 0;
    result = 31 * result + (int)(myChecksum ^ (myChecksum >>> 32));
    result = 31 * result + (isCritical ? 1 : 0);
    result = 31 * result + (isOptional ? 1 : 0);
    return result;
  }
}
