import _ from 'underscore';
import { IPageContent, IPageCellStyle } from './Page/Content';
import { IPageContentCell } from './Page/Content';

export interface IUtils {
  parseApiError: (err: any, def?: string) => string;
  clonePageContent(content: IPageContent, removeStyles?: boolean): IPageContent;
  comparePageContent(currentContent: any, newContent: any, ignore_styles?: boolean): IUtilsDiff | false;
  mergePageContent(_original: any, _deltas?: any, style?: any): any;
  getDefaultCellStyle(): IPageCellStyle;
}

export interface IUtilsDiff {
  content: IPageContent;
  content_diff: IPageContent;
  colDiff: number;
  rowDiff: number; 
  sizeDiff: boolean;
}

class Utils implements IUtils {
  constructor() {
    return;
  }

  public static get DEFAULT_CELL_STYLE(): IPageCellStyle {
    return {
      'background-color': 'FFFFFF',
      color: '000000',
      'font-family': 'Arial',
      'font-size': '11pt',
      'font-style': 'normal',
      'font-weight': 'normal',
      height: '20px',
      'number-format': '',
      'text-align': 'left',
      'text-wrap': 'normal',
      'vertical-align': 'middle',
      width: '64px',
      tbs: 'none',
      rbs: 'none',
      bbs: 'none',
      lbs: 'none',
      tbc: '000000',
      rbc: '000000',
      bbc: '000000',
      lbc: '000000',
      tbw: 'none',
      rbw: 'none',
      bbw: 'none',
      lbw: 'none',
    }
  }

  public parseApiError(err: any, def: string = ''): string {
    let msg: string = def;

    if (err.data) {
      let keys: string[] = Object.keys(err.data);
      if (keys.length) {
        if (_.isArray(err.data[keys[0]])) {
          msg = err.data[keys[0]][0];
        } else if (typeof err.data[keys[0]] === 'string') {
          msg = err.data[keys[0]];
        } else {
          msg = def;
        }
      } else {
        msg = def;
      }
    } else {
      msg = def;
    }

    return msg;
  }

  public clonePageContent(content: IPageContent, removeStyles?: boolean): IPageContent {
    let copy: IPageContent = [];
    let deltaStyle: IPageCellStyle = {};

    for (let i: number = 0; i < content.length; i++) {
      copy[i] = [];

      for (let j: number = 0; j < content[i].length; j++) {
        let cell: IPageContentCell = { ...content[i][j] };
        let style: any = {};
        for (let k in cell.style) {
          if (cell.style[k] === deltaStyle[k]) continue;
          style[k] = cell.style[k];
        }
        deltaStyle = { ...cell.style };
        cell.style = removeStyles ? {} : style;
        if (cell.index) delete cell.index;
        // if (cell.formatting) delete cell.formatting;
        copy[i].push(cell);
      }
    }

    return copy;
  }

  public comparePageContent(currentContent: any, newContent: any, ignore_styles: boolean = false): IUtilsDiff | false {
    if (!currentContent || !newContent) {
      return false;
    }
    let diffContent: any = [];
    let sizeDiff: boolean = false;
    // compare
    for (let i: number = 0; i < newContent.length; i++) {
      for (let k: number = 0; k < newContent[i].length; k++) {
        let diff: boolean = false;
        if (currentContent[i] && currentContent[i][k]) {
          // check for value changes
          if (newContent[i][k].value !== currentContent[i][k].value) {
            diff = true;
          }
          // check for style changes
          if (!diff && !ignore_styles) {
            for (let attr in newContent[i][k].style) {
              if (newContent[i][k].style[attr] !== currentContent[i][k].style[attr]) {
                diff = true;
                if (['width', 'height'].indexOf(attr) > -1) sizeDiff = true;
                break;
              }
            }
          }
        } else {
          diff = true;
        }
        if (diff) {
          if (!diffContent[i]) {
            diffContent[i] = [];
          }
          diffContent[i][k] = newContent[i][k];
        }
      }
    }
    if (
      diffContent.length ||
      newContent.length < currentContent.length ||
      newContent[0].length < currentContent[0].length
    ) {
      let rowDiff: number = currentContent.length - newContent.length;
      let colDiff: number = currentContent[0].length - newContent[0].length;
      return { content: newContent, content_diff: diffContent, colDiff: colDiff, rowDiff: rowDiff, sizeDiff };
    }
    return false;
  }

  public mergePageContent(_original: any, _deltas?: any, style: IPageCellStyle = {}): any {
    let current: IPageContent = [];
    // let style: IPageCellStyle = merge({}, _defaultStyles);
    let colWidths: any[] = [];
    for (let rowIndex = 0; rowIndex < _original.length; rowIndex++) {
      let row = _original[rowIndex];
      current[rowIndex] = [];
      for (let colIndex = 0; colIndex < row.length; colIndex++) {
        let col: IPageContentCell;
        if (
          _deltas &&
          _deltas[rowIndex] &&
          _deltas[rowIndex][colIndex]
        ) {
          col = _deltas[rowIndex][colIndex];
          // col.style = merge({}, style, col.style);
          col.style = { ...row[colIndex].style, ...col.style };
          style = { ...style, ...row[colIndex].style };
        } else {
          col = {...row[colIndex]};
          col.style = {...style, ...col.style};
          delete col.dirty;
          if (col.checked !== undefined) delete col.checked;
          style = {...col.style};
        }
        if (!rowIndex && col.style) {
          colWidths[colIndex] = col.style.width;
        }
        if (col.style) col.style.width = colWidths[colIndex];
        // col.formatting = {};
        col.index = {
          row: rowIndex,
          col: colIndex,
        };
        current[rowIndex].push(col);
      }
    }
    return current;
  }

  public getDefaultCellStyle(): IPageCellStyle {
    return {
      'background-color': 'FFFFFF',
      color: '000000',
      'font-family': 'Arial',
      'font-size': '11pt',
      'font-style': 'normal',
      'font-weight': 'normal',
      height: '20px',
      'number-format': '',
      'text-align': 'left',
      'text-wrap': 'normal',
      'vertical-align': 'middle',
      width: '64px',
      tbs: 'none',
      rbs: 'none',
      bbs: 'none',
      lbs: 'none',
      tbc: '000000',
      rbc: '000000',
      bbc: '000000',
      lbc: '000000',
      tbw: 'none',
      rbw: 'none',
      bbw: 'none',
      lbw: 'none',
    };
  }
}

export default Utils;
