import * as React from 'react';
import { kebabCase, camelcase, isEmptyObj } from './common';
import { uniq as _uniq, map as _map } from 'lodash-es';

const PERCENTAGE_KEY_LIST = [
  'opacity',
  'order',
  'flex',
  'flexGrow',
  'flexShrink',
  'zIndex',
  'fontWeight',
  'borderImage',
];

const DISTANCE_KEY_LIST = ['top', 'right', 'bottom', 'left'];

export function _handleStyleNumValue(
  styleVal: string | number,
  addPXUnit: boolean
) {
  if (addPXUnit) {
    const value = `${styleVal}`;
    if (value.search(/^\d+$/) >= 0) {
      return value + 'px';
    }
  }
  return styleVal;
}

export function translateStyleToRpx(
  style: React.CSSProperties = {}
): React.CSSProperties {
  return translateStyleByHandler(style, toRPX);
}

export function translateStyleToRem(style) {
  return translateStyleByHandler(style, toREM);
}

export function translateStyleByHandler(style, handler) {
  return Object.keys(style).reduce((result, key) => {
    const value = style[key];
    if (PERCENTAGE_KEY_LIST.includes(key)) {
      setStyleValue(result, key, value);
    } else if (value !== undefined && value !== null) {
      setStyleValue(result, key, handler(value));
    }
    return result;
  }, {});
}

export function setStyleValue(object, key, value) {
  if (value === undefined || value === null || value === '') {
    return;
  }
  // 特殊样式移除
  if (key === 'open') {
    return;
  }

  if (isEmptyObj(value)) {
    return;
  }

  object[camelcase(key)] = value;
}

export function setDistanceStyle(
  style,
  distance,
  attr: string,
  addPXUnit: boolean
) {
  if (Object.keys(distance).length === 4) {
    if (_uniq(_map(distance, (val) => val)).length === 1) {
      // 4个值全相等的情况
      setStyleValue(
        style,
        camelcase(`${attr}`),
        _handleStyleNumValue(distance.top, addPXUnit)
      );
    } else if (
      distance.top === distance.bottom &&
      distance.left === distance.right
    ) {
      // 俩俩相等的情况
      setStyleValue(
        style,
        camelcase(`${attr}`),
        `${_handleStyleNumValue(
          distance.top,
          addPXUnit
        )} ${_handleStyleNumValue(distance.right, addPXUnit)}`
      );
    } else if (distance.left === distance.right) {
      setStyleValue(
        style,
        camelcase(`${attr}`),
        `${_handleStyleNumValue(
          distance.top,
          addPXUnit
        )} ${_handleStyleNumValue(
          distance.right,
          addPXUnit
        )} ${_handleStyleNumValue(distance.bottom, addPXUnit)}`
      );
    } else {
      setStyleValue(
        style,
        camelcase(`${attr}`),
        `${_handleStyleNumValue(
          distance.top,
          addPXUnit
        )} ${_handleStyleNumValue(
          distance.right,
          addPXUnit
        )} ${_handleStyleNumValue(
          distance.bottom,
          addPXUnit
        )} ${_handleStyleNumValue(distance.left, addPXUnit)}`
      );
    }
  } else {
    DISTANCE_KEY_LIST.forEach((key) => {
      if (distance[key] !== undefined)
        setStyleValue(
          style,
          camelcase(`${attr}_${key}`),
          _handleStyleNumValue(distance[key], addPXUnit)
        );
    });
  }
}

function calPxToREM(px) {
  if (Number.isNaN(px / 28)) return px.toString();
  if (+px === 0) {
    return '0';
  }
  return (px / 28).toFixed(4) + 'rem';
}

export function toREM(cssLen) {
  if (typeof cssLen === 'string') {
    const cssLenArr = cssLen.split(' ');
    return cssLenArr
      .map((attr) => {
        const matchResult = attr.match(/^(-?\d+)(px)?$/);
        if (matchResult && matchResult[1]) {
          return calPxToREM(+matchResult[1]);
        }
        return attr;
      })
      .join(' ');
  }

  if (typeof cssLen === 'number') {
    return calPxToREM(cssLen);
  }
}

export function toRPX(cssLen: number | string): string {
  if (typeof cssLen === 'string') {
    const cssLenArr = cssLen.split(' ');
    return cssLenArr
      .map((attr) => {
        const matchResult = attr.match(/^(-?\d+)(px)?$/);
        if (matchResult && matchResult[1]) {
          return `${+matchResult[1]}rpx`;
        }
        return attr;
      })
      .join(' ');
  }
  return `${cssLen}rpx`;
}

export function toCssText(style, className = '.some-class-name') {
  const attrText = Object.keys(style)
    .map((key) => {
      const value = style[key];
      return `${kebabCase(key)}: ${value};`;
    })
    .join('\n');
  return `${className} { ${attrText} }\n`;
}
