importScripts('/lib/constructors/EventEmitter.js');
self.$$frameworkFlag = {};
var channelId;
var shouldReturnResult = false;
var requestId;
var originGlobal;
var payloads = [];

var origConsole = self.console;
var clearConsole = self.console.clear.bind(self.console);
var eventEmitter = new EventEmitter();

function postData(payload) {
  payloads.push(payload)
  try {
    // self.console.debug(`CallNative with some json data:`, payload);
    postMessage(payload);
  }
  catch (e) {
    self.console.warn(`CallNative with some non-json data:`, payload);
    payload = JSON.parse(JSON.stringify(payload));
    postMessage(payload);
  }
}

var _rewriteLog = function () {
  var LEVELS = ['error', 'warn', 'info', 'log', 'debug'];
  var backupConsole = {
    error: origConsole.error,
    warn: origConsole.warn,
    info: origConsole.info,
    log: origConsole.log,
    debug: origConsole.debug
  };

  function resetConsole() {
    self.console.error = backupConsole.error;
    self.console.warn = backupConsole.warn;
    self.console.info = backupConsole.info;
    self.console.log = backupConsole.log;
    self.console.debug = backupConsole.debug;
    self.console.time = origConsole.time;
    self.console.timeEnd = origConsole.timeEnd;
  }

  function noop() {}
  return function (logLevel) {
    resetConsole();
    LEVELS.slice(LEVELS.indexOf(logLevel) + 1).forEach(function (level) {
      self.console[level] = noop;
    })
  }
}();

onmessage = function (message) {
  eventEmitter.emit(message.data && message.data.method, message.data)
};

self.callNativeModule = function () {
  var message = {
    method: 'WxDebug.syncCall',
    params: {
      method: 'callNativeModule',
      args: Array.prototype.slice.call(arguments)
    },
    channelId: channelId
  }
  var result = syncRequest(message);
  if (shouldReturnResult && requestId) {
    postData({
      id: requestId,
      result: null,
      error: {
        errorCode: 0
      }
    });
  }
  if (result && result.error) {
    self.console.error(result.error);
    // throw new Error(result.error);
  }
  else return result && result.ret;
}

self.callNativeComponent = function () {
  var message = {
    method: 'WxDebug.syncCall',
    params: {
      method: 'callNativeComponent',
      args: Array.prototype.slice.call(arguments)
    },
    channelId: channelId
  }
  var result = syncRequest(message);
  if (result.error) {
    self.console.error(result.error);
    // throw new Error(result.error);
  }
  else return result.ret;
};

self.callNative = function (instance, tasks, callback) {
  for (var i = 0; i < tasks.length; i++) {
    var task = tasks[i];
    if (task.method == 'addElement') {
      for (var key in task.args[1].style) {
        if (Number.isNaN(task.args[1].style[key])) {
          self.console.error('invalid value [NaN] for style [' + key + ']', task);        }
      }
    }
  }
  var payload = {
    method: 'WxDebug.callNative',
    params: {
      instance: instance,
      tasks: tasks,
      callback: callback
    }
  };
  postData(payload);
};

self.responseInitJsFramework = function (result) {
  var payload = {
    method: 'WxDebug.responseInitJsFramework',
    params: {
      result: result
    }
  };
  postData(payload);
};

self.responseGetConsumeQueue = function (result) {
  var payload = {
    method: 'WxDebug.responseGetConsumeQueue',
    params: {
      result: result
    }
  };
  postData(payload);
};

self.responseExecJs = function (result) {
  var payload = {
    method: 'WxDebug.responseExecJs',
    params: {
      result: result
    }
  };
  postData(payload);
};


eventEmitter.on('WxDebug.initJSRuntime', function (message) {
  channelId = message.channelId;
  importScripts(message.params.url);
  self.responseInitJsFramework("1");
  //_rewriteLog(message.params.env.WXEnvironment.logLevel);
});

eventEmitter.on('WxDebug.getConsumeQueue', function (message) {
  var result = execCommandAndConsumeQueue(message.params.args);
  self.responseGetConsumeQueue(result);
});

eventEmitter.on('WxDebug.changeLogLevel', function (message) {
  self.WXEnvironment.logLevel = message.params;
});

eventEmitter.on('WxDebug.importScript', function (data) {
  if (data.params.sourceUrl) {
    importScripts(data.params.sourceUrl);
  }
  else {
    new Function('', data.params.source)();
  }
  self.responseExecJs("1");
})

function dump(id) {
  postMessage({
    method: 'WxRuntime.dom',
    params: getRoot(id)
  })
}

function syncRequest(data) {
  var request = new XMLHttpRequest();
  request.open('POST', '/syncApi', false); // `false` makes the request synchronous
  request.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
  request.send(JSON.stringify(data));
  if (request.status === 200) {
    return JSON.parse(request.responseText);
  }
  else {
    return {
      error: request.responseText
    };
  }
}
