import {asyncReplace} from 'stc-helper';
import {isMaster} from 'cluster';
import InvokePlugin from 'stc-plugin-invoke';

/**
 * stc plugin abstract class
 */
export default class StcPlugin {
  /**
   * constructor
   */
  constructor(file, opts = {}){
    this.file = file;
    this.options = opts.options || {};
    this.config = opts.config;
    this.cluster = opts.cluster;
    this.fileManage = opts.fileManage;
    //can not use extConf in sub plugins
    this.extConf = opts.extConf || {};
  }
  /**
   * get file content
   */
  getContent(encoding){
    if(isMaster){
      return this.file.getContent(encoding);
    }
    return this.cluster.invoke({
      method: 'getContent',
      args: [encoding],
      file: this.file.path,
      options: this.options
    });
  }
  /**
   * set file content
   */
  setContent(content){
    if(!isMaster){
      throw new Error('setContent method must be invoked in master');
    }
    this.file.setContent(content);
    return this;
  }
  /**
   * get file ast
   */
  async getAst(){
    //force in master invoked
    if(this.extConf.forceInMaster){
      return this.file.getAst();
    }
    
    if(isMaster){
      if(this.file.hasAst()){
        return this.file.getAst();
      }
      let content = await this.getContent('utf8');
      //get ast in worker parsed
      let ret = await this.cluster.doTask({
        type: 'getAst',
        content,
        file: this.file.path
      });
      this.file.setAst(ret);
      return ret;
    }
    //get ast from master
    return this.cluster.invoke({
      method: 'getAst',
      file: this.file.path,
      options: this.options
    })
  }
  /**
   * set ast
   */
  setAst(ast){
    if(!isMaster){
      throw new Error('setAst must be invoked in master');
    }
    this.file.setAst(ast);
    return this;
  }
  /**
   * add file dependence
   */
  addDependence(dependencies){
    if(!isMaster){
      throw new Error('addDependence must be invoked in master');
    }
  }
  /**
   * add file
   */
  addFile(filePath){
    if(!isMaster){
      throw new Error('addFile must be invoked in master');
    }
  }
  /**
   * invoke plugin
   */
  invokePlugin(plugin, file){
    let instance = new InvokePlugin(olugin, file, {
      config: this.config,
      options: this.options,
      fileManage: this.fileManage,
      cluster: this.cluster,
      extConf: this.extConf
    });
    return instance.run();
  }
  /**
   * async content replace
   * must be use RegExp
   */
  asyncReplace(content = '', replace, callback){
    return asyncReplace(content, replace, callback);
  }
  
  /**
   * run
   */
  run(){
    
  }
  /**
   * update
   */
  update(){
    
  }
}
@@ -13,16 +13,35 @@
 cReplace
+, isArray, isString
 %7D from '
@@ -132,16 +132,41 @@
 invoke';
+%0Aimport path from 'path';
 %0A%0A/**%0A *
@@ -1681,17 +1681,18 @@
 s%0A    %7D)
+;
 %0A
-
   %7D%0A  /*
@@ -2010,32 +2010,569 @@
 master');%0A    %7D%0A
+    if(!isArray(dependencies))%7B%0A      dependencies = %5Bdependencies%5D;%0A    %7D%0A    let currentFilePath = path.dirname(this.file.path);%0A    dependencies = dependencies.map(item =%3E %7B%0A      if(!isString(item))%7B%0A        return item;%0A      %7D%0A      let filepath = path.resolve(currentFilePath, item);%0A      let file = this.fileManage.getFileByPath(filepath);%0A      if(!file)%7B%0A        throw new Error(%60file $%7Bitem%7D is not exist in $%7Bthis.file.path%7D%60);%0A      %7D%0A      return file;%0A    %7D);%0A    this.file.dependence.add(dependencies);%0A    return this;%0A
   %7D%0A  /**%0A   * a
@@ -2792,17 +2792,17 @@
 ePlugin(
-o
+p
 lugin, f

Add addDependence method