import {injectable, inject} from 'inversify';
import {Serialize, DeserializeInto, autoserializeAs, Deserialize} from 'cerialize';
import {
  FullPipeline, DecryptAndUnTarOptions, UnZipFileOptions, MergePcapFilesOptions
} from "../../interfaces/vita-options-results";
import {CommandUtil} from "firmament-yargs";
import {DecryptAndUnTarOptionsImpl} from "./decrypt-and-untar-options-impl";
import {UnZipFileOptionsImpl} from "./unzip-file-options-impl";
import {MergePcapFilesOptionsImpl} from "./merge-pcap-files-options-impl";
import kernel from "../../inversify.config";
const fileExists = require('file-exists');
const path = require('path');
const fs = require('fs');

@injectable()
export class FullPipelineImpl implements FullPipeline {
  private commandUtil: CommandUtil;
  @autoserializeAs(DecryptAndUnTarOptionsImpl) decryptAndUnTarOptions: DecryptAndUnTarOptions;
  @autoserializeAs(UnZipFileOptionsImpl) unZipFileOptions: UnZipFileOptions;
  @autoserializeAs(MergePcapFilesOptionsImpl) mergePcapFilesOptions: MergePcapFilesOptions;

  constructor(@inject('CommandUtil')_commandUtil: CommandUtil,
              @inject('DecryptAndUnTarOptions')_decryptAndUnTarOptions: DecryptAndUnTarOptions,
              @inject('UnZipFileOptions')_unZipFileOptions: UnZipFileOptions,
              @inject('MergePcapFilesOptions')_mergePcapFilesOptions: MergePcapFilesOptions) {
    this.commandUtil = _commandUtil;
    this.decryptAndUnTarOptions = _decryptAndUnTarOptions;
    this.unZipFileOptions = _unZipFileOptions;
    this.mergePcapFilesOptions = _mergePcapFilesOptions;
  }

  fromArgv(argv: any): FullPipeline {
    if (argv.jsonIn && fileExists(argv.jsonIn)) {
      let fullPipeline = this.fromJsonFile(argv.jsonIn);
      this.decryptAndUnTarOptions = fullPipeline.decryptAndUnTarOptions;
      this.unZipFileOptions = fullPipeline.unZipFileOptions;
      this.mergePcapFilesOptions = fullPipeline.mergePcapFilesOptions;
      return this;
    }
    this.decryptAndUnTarOptions.fromArgv(argv);
    this.mergePcapFilesOptions.fromArgv(argv);
    return this;
  }

  fromJson(json: string): FullPipeline {
    DeserializeInto(JSON.parse(json), FullPipelineImpl, this);
    return this;
  }

  toJson(): string {
    let obj = Serialize(this);
    let json = JSON.stringify(obj, undefined, 2);
    return json;
  }

  fromJsonFile(jsonFile: string): FullPipeline {
    let fullInputPath = this.commandUtil.getConfigFilePath(jsonFile);
    let json = fs.readFileSync(fullInputPath, {encoding: 'utf-8'});
    return this.fromJson(json);
  }

  toJsonFile(jsonFile: string) {
    let fullOutputPath = this.commandUtil.getConfigFilePath(jsonFile);
    this.validate();
    fs.writeFileSync(fullOutputPath, this.toJson());
  }

  validate() {
    this.decryptAndUnTarOptions.validate();
    if (!this.unZipFileOptions.targetFolder) {
      this.unZipFileOptions.targetFolder = this.decryptAndUnTarOptions.targetFolder;
    }
    this.unZipFileOptions.validate();
    if (!this.mergePcapFilesOptions.targetFolder) {
      this.mergePcapFilesOptions.targetFolder = this.decryptAndUnTarOptions.targetFolder;
    }
    this.mergePcapFilesOptions.validate();
  }
}
