import { ISafeAny } from './label.type';

export function functionProxy(origin: ISafeAny) {
  const obj = [
    'init',
    'setPage',
    'setZoom',
    'setLabelMode',
    'setPdfMode',
    'setLabels',
    'restore',
    'search',
    'scrollToLabel',
    'scrollToLabelByIdx',
    'scrollToTableCell',
    'setTables',
    'getTableMatrix',
    'getViewport',
    'getSelectedLabels',
    'resetLabelsStyle',
    'resetSelectedLabels',
    'getDocContent',
    'enableMergeOrSplitTables'
  ].reduce((pre, key) => {
    (pre as ISafeAny)[key] = function proxy() {
      const timeTag = `Execution Time`;
      console.group(`[@bixi/label] Proxy ${key}`);
      console.log(...arguments);
      // tslint:disable-next-line: no-console
      console.time(timeTag);
      let result;
      try {
        result = origin[key](...arguments);
      } catch (error) {
        console.error(`[@bixi/label] excute proxy.${key} failed`);
        console.error(error);
      }
      // tslint:disable-next-line: no-console
      console.timeEnd(timeTag);
      console.groupEnd();
      return result;
    };
    return pre;
  }, {});
  return obj;
}

export function Log() {
  return (_target: ISafeAny, _propKey: ISafeAny, desc: TypedPropertyDescriptor<ISafeAny>) => {
    return {
      ...desc,
      value() {
        if ((this as ISafeAny).dev === true) {
          console.group(`[@bixi/label] hub ${_propKey}`);
          console.log(...arguments);
          let result;
          // tslint:disable-next-line: no-console
          console.time(_propKey);
          result = desc.value.bind(this)(...arguments);
          // tslint:disable-next-line: no-console
          console.timeEnd(_propKey);
          console.groupEnd();
          return result;
        }
        return desc.value.bind(this)(...arguments);
      }
    };
  };
}

export function Safe() {
  return (_target: ISafeAny, _propKey: ISafeAny, desc: TypedPropertyDescriptor<ISafeAny>) => {
    return {
      ...desc,
      value() {
        if ((this as ISafeAny).ready === false) {
          console.error('[@bixi/label] DANGEROUS!!! Call method before initialization:', _propKey);
          return void 0;
        }
        return desc.value.bind(this)(...arguments);
      }
    };
  };
}
