'use strict';

const LayoutMetrics = (() => {
  const TAG_PATTERN = /<[^>]+>/g;
  const PATH_PATTERN = /pathimg/g;
  const ARROW_PATTERN = /arrowimg/g;
  const WHITESPACE_PATTERN = /\s{1,}/g;

  const countMatches = (text, pattern) => {
    return (text.match(pattern) || []).length;
  };

  const createRenderingContext = (font) => {
    const canvas = document.createElement('canvas');
    const renderingContext = canvas.getContext('2d');
    renderingContext.font = font;
    return renderingContext;
  };

  const computeTextWidth = (value, letterSpacing, renderingContext) => {
    const text = _.unescape(value.replace(TAG_PATTERN, '').replace(WHITESPACE_PATTERN, ' ').trim());
    return text.length ? renderingContext.measureText(text).width + letterSpacing * (text.length - 1) : 0;
  };

  return {
    /**
     * The selector (path) width calculation is not very accurate - the current implementation uses the maximum possible image width.
     * In order to improve the result we need to calculate the image sizes in advance, so as not to resort to using DOM or asynchronous code.
     */
    initialize() {
      const style = window.getComputedStyle(document.querySelector('.main'));
      const css = (property) => parseFloat(style.getPropertyValue(property)) || 0;

      const titleRenderingContext = createRenderingContext(style.getPropertyValue('--title-font'));
      const bodyRenderingContext = createRenderingContext(style.getPropertyValue('--body-font'));
      const innerOffset = 2 * (css('--border-width') + css('--action-padding'));
      const letterSpacing = css('--letter-spacing');
      const arrowWidth = css('--arrow-width');
      const pathWidth = css('--path-width');
      const groupSize = css('--group-size');
      const iconsSize = css('--icons-size');
      const titleGap = css('--title-gap');

      return {
        /* | innerOffset / 2 | groupSize | titleGap | textWidth | titleGap | iconsSize | innerOffset / 2 | */
        computeTitleWidth(title, isFoldable = false) {
          const textWidth = computeTextWidth(title, letterSpacing, titleRenderingContext);

          if (textWidth === 0) {
            return 0;
          }

          return textWidth + innerOffset + (groupSize + 2 * titleGap + (isFoldable ? iconsSize : 0));
        },

        /* | innerOffset / 2 | textWidth | pathWidth * n | arrowWidth * n | innerOffset / 2 | */
        computeBodyWidth(body, isFoldable = false) {
          const textWidth = computeTextWidth(body, letterSpacing, bodyRenderingContext);

          if (textWidth === 0) {
            return 0;
          }

          return (
            textWidth +
            innerOffset +
            countMatches(body, PATH_PATTERN) * pathWidth +
            countMatches(body, ARROW_PATTERN) * arrowWidth
          );
        },

        availWidth: window.innerWidth - (parseFloat(style.paddingLeft) + parseFloat(style.paddingRight)),
      };
    },
  };
})();
