/**
 * Copyright (c) Tiny Technologies, Inc. All rights reserved.
 * Licensed under the LGPL or a commercial license.
 * For LGPL see License.txt in the project root for license information.
 * For commercial licenses see https://www.tiny.cloud/
 */

import { Arr } from '@ephox/katamari';
import { PlatformDetection } from '@ephox/sand';
import { Attr, Css, SelectorFilter } from '@ephox/sugar';

const attr = 'data-ephox-mobile-fullscreen-style';
const siblingStyles = 'display:none!important;';
const ancestorPosition = 'position:absolute!important;';
const ancestorStyles = 'top:0!important;left:0!important;margin:0' +
  '!important;padding:0!important;width:100%!important;';
const bgFallback = 'background-color:rgb(255,255,255)!important;';

const isAndroid = PlatformDetection.detect().os.isAndroid();

const matchColor = function (editorBody) {
  // in iOS you can overscroll, sometimes when you overscroll you can reveal the bgcolor of an element beneath,
  // by matching the bg color and clobbering ensures any reveals are 'camouflaged' the same color
  const color = Css.get(editorBody, 'background-color');
  return (color !== undefined && color !== '') ? 'background-color:' + color + '!important' : bgFallback;
};

// We clobber all tags, direct ancestors to the editorBody get ancestorStyles, everything else gets siblingStyles
const clobberStyles = function (container, editorBody) {
  const gatherSibilings = function (element) {
    const siblings = SelectorFilter.siblings(element, '*');
    return siblings;
  };

  const clobber = function (clobberStyle) {
    return function (element) {
      const styles = Attr.get(element, 'style');
      const backup = styles === undefined ? 'no-styles' : styles.trim();

      if (backup === clobberStyle) {
        return;
      } else {
        Attr.set(element, attr, backup);
        Attr.set(element, 'style', clobberStyle);
      }
    };
  };

  const ancestors = SelectorFilter.ancestors(container, '*');
  const siblings = Arr.bind(ancestors, gatherSibilings);
  const bgColor = matchColor(editorBody);

  /* NOTE: This assumes that container has no siblings itself */
  Arr.each(siblings, clobber(siblingStyles));
  Arr.each(ancestors, clobber(ancestorPosition + ancestorStyles + bgColor));
  // position absolute on the outer-container breaks Android flex layout
  const containerStyles = isAndroid === true ? '' : ancestorPosition;
  clobber(containerStyles + ancestorStyles + bgColor)(container);
};

const restoreStyles = function () {
  const clobberedEls = SelectorFilter.all('[' + attr + ']');
  Arr.each(clobberedEls, function (element) {
    const restore = Attr.get(element, attr);
    if (restore !== 'no-styles') {
      Attr.set(element, 'style', restore);
    } else {
      Attr.remove(element, 'style');
    }
    Attr.remove(element, attr);
  });
};

export default {
  clobberStyles,
  restoreStyles
};