import {createElement} from "../../utils/create";
import {Container, Text, Sprite, Texture} from "pixi.js";
import ModalBackground from "./ModalBackground.js";
import Button from "./Button.js";
import {SETTINGS} from "../../constants/constants";
import {ScrollBox} from "@pixi/ui";
import ScrollBar from "./ScrollBar.js";
import {createStyles} from "../../utils/styles";
import {capitalizeFirstLetter} from "../../utils/utils";
import Locator from "../../services/Locator";
import {ANALYTICS_EVENTS} from "../../services";

/**
 * Создает модальное окно выбора ставки.
 * @param {{resolution: number}} options Параметры отображения.
 * @returns {Container} Экземпляр контейнера выбора ставки.
 */
export default function BetPicker(options) {

  const refs = {};

  const rootStyle = createStyles({
    scale: () => {
      const factorV = 0.5;
      return {x: factorV, y: factorV};
    },
    x: () => Math.max(Locator.viewport.left + 130, 200),
    y: () => {
      return SETTINGS.viewport.height - bgStyle.height * 0.5 - 60;
    },
    '(max-aspect-ratio: 1.56)': {
      scale: () => {
        const factorV = 0.5;
        return {x: factorV, y: factorV};
      },
      x: () => Math.max(Locator.viewport.left + 100, 200),
    },
    '(max-aspect-ratio: 1.113)': {
      scale: () => {
        const factorV = 0.5;
        return {x: factorV, y: factorV};
      },
      x: () => {
        return SETTINGS.viewport.width * 0.5 - bgStyle.width * 0.25;
      },
      y: () => {
        return SETTINGS.viewport.height * 0.5 - bgStyle.height * 0.25;
      },
    },
    '(max-height: 500px) and (orientation: landscape)': {
      scale: {x: 1, y: 1},
      x: () => Locator.viewport.left,
      y: () => 0,
    },
    '(orientation: portrait)': {
      scale: {x: 1, y: 1},
      x: () => Locator.viewport.left,
      y: () => 0,
    }
  });

  const bgStyle = createStyles({
    width: 460,
    height: 290,
    radius: 10,
    fill: 0x161616,
    '(max-height: 550px) and (orientation: landscape)': {
      radius: 0,
      width: () => SETTINGS.viewport.width * Locator.viewport.cropWidthRatio,
      height: () => SETTINGS.viewport.height,
    },
    '(orientation: portrait)': {
      radius: 0,
      width: () => SETTINGS.viewport.width * Locator.viewport.cropWidthRatio,
      height: () => SETTINGS.viewport.height,
    }
  });

  const maskStyle = createStyles({
    width: 445,
    height: 290,
    tint: 0xff0000,
    texture: Texture.WHITE
  });

  const textStyle = {
    fontFamily: 'Oxanium, Opensans',
    fill: 0xffffff,
    fontWeight: 'normal',
    fontSize: 24,
  };

  const titleStyle = createStyles({
    style: {...textStyle, fontWeight: "bold"},
    x: 16,
    y: 14,
    anchor: {x: 0, y: 0},
    scale: {x: 1, y: 1},
    '(max-height: 500px) and (orientation: landscape)': {
      anchor: {x: 0.5, y: 0},
      x: () => bgStyle.width() * 0.5,
      y: 20,
      style: {...textStyle, fontSize: 80},
      scale: {x: 0.5, y: 0.5},
    },
    '(orientation: portrait)': {
      anchor: {x: 0.5, y: 0},
      x: () => bgStyle.width() * 0.5,
      y: 30,
      style: {...textStyle, fontSize: 40},
      scale: {x: 0.5, y: 0.5},
    }
  });

  const closeBtnStyle = createStyles({
    x: () => bgStyle.width - 26,
    y: 30,
    scale: {x: 1, y: 1},
    '(max-height: 500px) and (orientation: landscape)': {
      x: () => bgStyle.width() * 0.9,
      y: 45,
      scale: {x: 1.5, y: 1.5},
    },
    '(orientation: portrait)': {
      x: () => bgStyle.width() * 0.9,
      y: 42,
      scale: {x: 0.75, y: 0.75},
    }
  });

  const buttonStyle = createStyles({
    scale: {x: 0.6, y: 0.6},
    '(max-height: 500px) and (orientation: landscape)': {
      scale: {x: 0.8, y: 0.8},
    },
    '(orientation: portrait)': {
      scale: {x: 0.45, y: 0.45},
    }
  });

  const buttonsLayout = createStyles({
    x: (i) => i % 5 * 85 + 37,
    y: (i) => Math.floor(i / 5) * 45 + 16,
    columns: 5,
    '(max-height: 500px) and (orientation: landscape)': {
      x: (i) => i % 5 * 110 + 50,
      y: (i) => Math.floor(i / 5) * 55 + 25,
      columns: 5,
    },
    '(orientation: portrait)': {
      columns: 3,
      x: (i) => i % 3 * 62 + 34,
      y: (i) => Math.floor(i / 3) * 35 + 15,
    }
  });

  const containerStyle = createStyles({
    x: 15,
    y: 65,
    '(max-height: 500px) and (orientation: landscape)': {
      x: () => bgStyle.width() * 0.5 - 540 / 2,
      y: () => 70,
    },
    '(orientation: portrait)': {
      x: () => bgStyle.width() * 0.5 - 105,
      y: () => 70,
    }
  });

  const scrollBarStyle = createStyles({
    trackWeight: () => 290 - 80,
    trackHeight: 10,
    x: () => 445 - 30 + 10,
    '(max-height: 550px) and (orientation: landscape)': {
      trackWeight: () => 360,
      trackHeight: 4,
      x: () => 540 + 10,
    },
    '(orientation: portrait)': {
      trackWeight: () => 330,
      trackHeight: 4,
      x: () => 190 + 10,
    }
  });

  let buttons = [];
  let selectedIndex = 0;
  const createButtons = (bets) => {
    buttons.forEach(b => b.destroy());
    scroll.removeItems();
    buttons = bets.map((betData, i) => {
      const btn = createElement(Button, {
        args: ['bet_picker_btn', betData.value, options.resolution],
        textStyle: {...textStyle, fontSize: 24, fontWeight: 400},
        styles: buttonStyle,
      });
      if (betData.selected) {
        btn.select();
        selectedIndex = i;
      }
      if (!betData.available) btn.disable();

      btn.on('up', () => {
        view.emit('pick', {index: i});
        view.hide();
      });
      return btn;
    });
    scroll.addItems(buttons);
    resizeButtons();
  };

  const scrollStyle = createStyles({
    width: () => 445 - 30,
    height: () => 290 - 80,
    elementsMargin: 0,
    vertPadding: 0,
    horPadding: 0,
    '(max-height: 550px) and (orientation: landscape)': {
      width: () => 540,
      height: () => 360,
      elementsMargin: 0,
      vertPadding: 0,
      horPadding: 0,
    },
    '(orientation: portrait)': {
      width: () => 195,
      height: () => 330,
      elementsMargin: 0,
      vertPadding: 0,
      horPadding: 0,
    }
  });

  let visibleItems = buttons.map(() => false);

  const scroll = createElement(ScrollBox, {
    name: 'scrollbox',
    ref: (el) => {
      refs.scrollbox = el;
    },
    args: [{
      width: scrollStyle.width(),
      height: scrollStyle.height(),
      elementsMargin: scrollStyle.elementsMargin,
      items: buttons,
      disableEasing: true,
      vertPadding: scrollStyle.elementsMargin,
      horPadding: scrollStyle.elementsMargin,
    }],
    visible: true,
  });
  scroll.resize();
  scroll.onProximityChange.connect((e) => {
    visibleItems[e.index] = e.inRange;
    const firstItemInRange = visibleItems.findIndex((inRange) => inRange);
    const lastItemInRange = Math.min(visibleItems.findLastIndex((inRange) => inRange), buttons.length);
    refs.scrollBar.progress = firstItemInRange / buttons.length;
    refs.scrollBar.handleWidth = refs.scrollBar.trackWidth * (visibleItems.filter(item => item).length / buttons.length);
  });

  const scrollBar = createElement(ScrollBar, {
    angle: 90,
    styles: scrollBarStyle,
    ref: (el) => {
      refs.scrollBar = el;
    },
  });
  scrollBar.on("scroll", (e) => {
    // scroll.scrollY = scroll.scrollY - e.deltaX;
    scroll.scrollToPosition({x: 0, y: e.deltaX - scroll.scrollY});
  });

  const resizeButtons = () => {
    buttons.forEach((button, i) => {
      button.styles = buttonStyle;
      button.x = buttonsLayout.x(i);
      button.y = buttonsLayout.y(i);
    });
  };

  const view = createElement(
    Container,
    {
      styles: rootStyle,
      eventMode: 'static',
    },
    createElement(ModalBackground, {
      name: 'back',
      styles: bgStyle,
    }),
    createElement(Text, {
      name: 'title',
      text: capitalizeFirstLetter(Locator.locales.get("total_bet")),
      styles: titleStyle,
      visible: true,
      resolution: options.resolution,
    }),
    createElement(Button, {
      name: 'close',
      args: ['modal_close_btn', '', options.resolution],
      styles: closeBtnStyle,
      visible: true,
    }),
    createElement(
      Container,
      {
        name: 'container',
        styles: containerStyle,
        ref: (el) => {
          refs.container = el;
        },
      },
      scroll,
      createElement(Sprite, {
        texture: Texture.WHITE,
        visible: false,
      }),
      scrollBar,
    ),
    createElement(Sprite, {
      texture: Texture.WHITE,
      visible: false,
    }),
  );

  view.createButtons = createButtons.bind(this);

  view.resize = () => {
    view.getChildByName('back').styles = bgStyle;
    view.getChildByName('title').styles = titleStyle;
    view.getChildByName('close').styles = closeBtnStyle;
    view.getChildByName('container').styles = containerStyle;

    refs.scrollbox.init({
      width: scrollStyle.width(),
      height: scrollStyle.height(),
      elementsMargin: scrollStyle.elementsMargin,
      vertPadding: scrollStyle.vertPadding,
      horPadding: scrollStyle.horPadding,
      padding: scrollStyle.padding,
      disableEasing: true,
    });
    resizeButtons();
    refs.scrollbox.resize(true);
    refs.scrollbox.update(0);



    refs.scrollBar.styles = scrollBarStyle;
    refs.scrollBar.trackWidth = refs.scrollbox.height;
    refs.scrollbox.scrollTo(buttons.findIndex((btn) => btn.isSelected) || 0);
    view.styles = rootStyle;

    visibleItems = buttons.map((btn) => {
      return scroll.isItemVisible(btn);
    });

    const firstItemInRange = visibleItems.findIndex((inRange) => inRange);
    refs.scrollBar.progress = firstItemInRange / buttons.length;
    refs.scrollBar.handleWidth = refs.scrollBar.trackWidth * (visibleItems.filter(item => item).length / buttons.length);
  };

  view.visible = false;

  const isClickOnPicker = (e) => {
    const objects = Locator.renderer.events.rootBoundary.hitTestRecursive(
      view,
      'static',
      e.global,
      (d, l) => Locator.renderer.events.rootBoundary.hitTestFn(d, l),
      (d, l) => Locator.renderer.events.rootBoundary.hitPruneFn(d, l)
    );
    return objects && objects.length > 0;
  };

  view.isClickOnPicker = isClickOnPicker.bind(this);

  view.getChildByName('close').on('up', () => {
    view.visible = false;
  });

  view.hide = () => {
    view.visible = false;
  };


  view.show = () => {
    view.visible = true;
    scroll.scrollTo(selectedIndex);
    view.resize();

    Locator.analytics.track(ANALYTICS_EVENTS.BETS_LIST_OPENED);
  };

  view.update = () => {
    buttons.forEach((btn) => btn.update());
    view.getChildByName('close').update();
  };


  return view;
}
