
import { version } from "../package.json";

import File from "./file";
import coreOptions from "./options/core-config";
import fileOptions from "./options/file-config";
import template from "babel-template";

import * as util from "./util";
import * as types from "comal-types";
import traverse from "comal-traverse";
import OptionsLoader from "./options/loader";

import isFunction from "lodash/isFunction";
import fs from "fs";

import Pipeline from "./transformation/pipeline";

export default class Api {
  comalVersion = version;
  File = File;
  coreOptions = coreOptions;
  fileOptions = fileOptions;
  template = template;
  util = util;
  types = types;
  traverse = traverse;
  OptionsLoader = OptionsLoader;
  Pipeline = Pipeline;

  constructor(meta) {
    this.transformFile = this.transformFile.bind(this);
    this.transformFileSync = this.transformFileSync.bind(this);

    let pipeline = new Pipeline(meta, this);
    // this.analyse = pipeline.analyse.bind(pipeline);
    this.transform = pipeline.transform.bind(pipeline);
    this.transformFromAst = pipeline.transformFromAst.bind(pipeline);
  }

  transformFile(filename: string, opts?: Object, callback: Function) {
    if (isFunction(opts)) {
      callback = opts;
      opts = {};
    } else if (opts == null) {
      opts = {};
    }

    opts.filename = filename;

    fs.readFile(filename, "utf8", (err, code) => {
      let result;

      if (!err) {
        try {
          result = this.transform(code, opts);
        } catch (_err) {
          err = _err;
        }
      }

      if (err) {
        callback(err);
      } else {
        callback(null, result);
      }
    });
  }

  transformFileSync(filename: string, opts?: Object = {}): string {
    opts.filename = filename;
    return this.transform(fs.readFileSync(filename, "utf8"), opts);
  }
}

@@ -474,16 +474,68 @@
 peline%22;
+%0Aimport type Transformation from %22./transformation%22;
 %0A%0Aexport
@@ -1162,237 +1162,1154 @@
 e);%0A
-  %7D%0A%0A  transformFile(filename: string, opts?: Object, callback: Function) %7B%0A    if (isFunction(opts)) %7B%0A      callback =
+%0A    this.createTransform = pipeline.createTransform.bind(pipeline);%0A    this.exec = pipeline.exec.bind(pipeline);%0A  %7D%0A%0A  transformFile(filename: string, opts?: Object, callback: Function) %7B%0A    %5Bopts, callback%5D = Api.maybeOptsBeforeCallback(opts, callback);%0A%0A    opts.filename = filename;%0A%0A    return this._wrapReadFile(filename, callback, (code) =%3E this.transform(code,
  opts
+))
 ;%0A  
-    opts = %7B%7D;%0A    %7D else if (opts == null) %7B%0A      opts = %7B%7D;%0A    %7D%0A%0A    opts.filename = filename;%0A
+%7D%0A%0A  transformFileSync(filename: string, opts?: Object = %7B%7D) %7B%0A    opts.filename = filename;%0A    return this.transform(fs.readFileSync(filename, %22utf8%22), opts);%0A  %7D%0A%0A  // TODO: remove code duplication%0A  execFile(transformer: Transformation, filename: string, opts?: Object, callback: Function) %7B%0A    %5Bopts, callback%5D = Api.maybeOptsBeforeCallback(opts, callback);%0A%0A    opts.filename = filename;%0A%0A    return this._wrapReadFile(filename, callback, (code) =%3E this.exec(transformer, code, opts));%0A  %7D%0A%0A  execFileSync(transformer: Transformation, filename: string, opts?: Object = %7B%7D) %7B%0A    opts.filename = filename;%0A    return this.exec(transformer, fs.readFileSync(filename, %22utf8%22), opts);%0A  %7D%0A%0A  _wrapReadFile(filename: string, callback: Function, body: Function) %7B
 %0A   
@@ -2430,33 +2430,28 @@
 t = 
-this.transform(code, opts
+body.call(this, code
 );%0A 
@@ -2629,82 +2629,185 @@
 %0A%0A  
-transformFileSync(filename: string, opts?: Object = %7B%7D): string
+static maybeOptsBeforeCallback(opts?: Object, callback: Function) %7B%0A    if (isFunction(opts)) %7B%0A      callback = opts;%0A      opts = %7B%7D;%0A    %7D else if (opts == null)
  %7B%0A
+  
     opts
 .fil
@@ -2806,100 +2806,53 @@
 opts
-.filename = filename;%0A    return this.transform(fs.readFileSync(filename, %22utf8%22), opts)
+ = %7B%7D;%0A    %7D%0A    return %5Bopts, callback%5D
 ;%0A  %7D%0A
+%0A
 %7D%0A

add exec and createTransform to api