import Card from "../card/Card";
import ArrPrev from '/svg/arrow_active.svg';
import ArrNext from '/svg/arrow_active-back.svg';
import './CardSlider.scss';

const CardSlider = D.declare('view.cmp.CardSlider', (cfg) => {
    let current = [],
        hash = {},
        items = [],
        cardWidth = 160,
        minPadding = 10,
      mobilePadding = 10,
        wrap,
        width,
        fullCardsCount,
        padding,
        updateSize = function () {
            width = dom.clientWidth - paddingLeft - paddingRight;
            fullCardsCount = width / (cardWidth + minPadding) | 0;
            padding = mobile ? mobilePadding: (width - fullCardsCount * cardWidth) / (fullCardsCount - 1);
            wrap.style.width = (items.length * (padding + cardWidth) - padding) + 'px';
        },
        update = function () {
            updateSize();
            updateVisibleDom();
        };
    let paddingLeft = 30, paddingRight = 30, mobile = false;




    let waitTimeout = false;
    let tuning;
    let leftestItem = 0;
    let lastLeftestItem = 0;
    let leftButtonDisabled = new Store.Value.Boolean(true), rightButtonDisabled = new Store.Value.Boolean(true);

    let updateButtonsState = function() {
        let fromLeft = dom.scrollLeft;
        let firstItem = Math.round( fromLeft / ( cardWidth + padding ));
        leftButtonDisabled.set(firstItem===0);
        rightButtonDisabled.set(firstItem+fullCardsCount===items.length);
    };

    let untune = function() {
        updateButtonsState();
        tuning = false;
    };
    let tuneScrollPosition = function (x) {
        if(tuning)
            return untune();
        waitTimeout = false;
        tuning = true;
        let fromLeft = dom.scrollLeft;
        let firstItem, toLeft;
        if(x){
            firstItem = Math.round( fromLeft / ( cardWidth + padding ));
            if(firstItem+x<0 || firstItem+fullCardsCount+x>items.length){
                return untune();
            }

            toLeft = Math.round( (firstItem + x) * ( cardWidth + padding ));
        }else{
            firstItem = Math.round( fromLeft / ( cardWidth + padding ) - ( lastLeftestItem > leftestItem ? 0.4 : -0.4 ) );
            toLeft = Math.round( firstItem * ( cardWidth + padding ) );
        }
        let deltaMove = (toLeft - fromLeft) / Math.ceil(200 / (1000 / 60));
        while (deltaMove > 0 && deltaMove < 1) {
            deltaMove *= 2;
        }
        if (Math.abs(fromLeft + deltaMove - toLeft) > Math.abs(fromLeft - toLeft)) {
            deltaMove = toLeft - fromLeft;
        }
        let tune = function () {
            if (Math.abs(toLeft - dom.scrollLeft) > (cardWidth + padding)*1.3) {
                return untune();
            }
            if (Math.sign(toLeft - dom.scrollLeft) !== Math.sign(deltaMove)) {
                return untune();
            }
            if (Math.abs(dom.scrollLeft - toLeft) < Math.abs(deltaMove)) {
                dom.scrollLeft = toLeft;
                return untune();
            } else {
                dom.scrollLeft += deltaMove;
                requestAnimationFrame(tune);
            }
        };
        if (Math.abs(deltaMove) > 0) {
            requestAnimationFrame(tune);
        } else {
            return untune();
        }

    };
    let waitUntilDoNotTouchScroll = function () {
        if (tuning)
            return;

        lastLeftestItem = leftestItem;
        leftestItem = dom.scrollLeft / (cardWidth + padding);

        if (waitTimeout)
            clearTimeout(waitTimeout);
        waitTimeout = setTimeout(tuneScrollPosition, 80);
    };
    let dom;
    let theDOM = <div class="card-slider">
        <button class={D.cls(
                'button',
                'button--round',
                'card-slider__control',
                'card-slider__control--prev',
                {'card-slider__control-disabled': leftButtonDisabled}
            )} type="button"
                onClick={()=>{
                    tuneScrollPosition(-1);
                }}
                aria-label="Показать предыдущую карточку">
            <ArrPrev width="14" height="12"/>
        </button>
        <button class={D.cls(
                'button',
                'button--round',
                'card-slider__control',
                'card-slider__control--next',
                {'card-slider__control-disabled': rightButtonDisabled}
            )} type="button"
                onClick={()=>{
                    tuneScrollPosition(1);
                }}
                aria-label="Показать следующую карточку">
            <ArrNext width="14" height="12"/>
        </button>
        {dom = <div class='card-slider__scroller'>
            {wrap = <div class='card-slider__wrapper'>{' '}</div>}
        </div>}
    </div>;

    let lastFrom, lastTo, last = false;
    let updateVisibleDom = function () {
        let from = Math.floor(dom.scrollLeft / (cardWidth + padding) - 1),
            count = Math.ceil(dom.clientWidth / (cardWidth + padding)),
            to;
        to = from + count * 2;
        from -= count;
        from = Math.max(0, from);
        to = Math.min(to, items.length);

//console.log({from, to, cardWidth, padding})
        for (let i = from; i < to; i++) {
            if (!(i in hash)) {
                hash[i] = {
                    dom: (function (item, n) {
                        return <div className="card-slider__item">
                            <Card
                                type={'product,info,other'.split(',')[n % 3]}
                                disabled={n % 5 === 0}
                                seen={n % 4 === 0}
                                title={item.name}
                                image={item.image}
                            />
                        </div>
                    })(items[i], i),
                    inDOM: false,
                    x: 0
                };
            }
        }
        if (last) {
            for (let i = lastFrom; i < lastTo; i++) {
                if (i < from || i >= to) {
                    if (hash[i].inDOM) {
                        hash[i].inDOM = false;
                        wrap.removeChild(hash[i].dom);
                    }
                }
            }
        }
        for (let i = from; i < to; i++) {
            let x = paddingLeft + i * (cardWidth + padding);
            if (hash[i].x !== x) {
                hash[i].dom.style.left = (hash[i].x = x) + 'px';
            }
            if (!hash[i].inDOM) {
                wrap.appendChild(hash[i].dom);
                hash[i].inDOM = true;
            }
        }


        lastFrom = from;
        lastTo = to;
        last = true;
        updateButtonsState();
    };

    dom.addEventListener('scroll', Store.debounce(function () {
        requestAnimationFrame(updateVisibleDom);
        waitUntilDoNotTouchScroll();
    }, 1000 / 60));
    cfg.items(function (i) {
        items = i;
        //update();

        update();

    });

    tmpStore.sub('width', Store.debounce(function (w) {
        let firstItem = Math.round(dom.scrollLeft / (cardWidth + padding));
        update();
        dom.scrollLeft = firstItem * (cardWidth + padding);
    }, 30));

    tmpStore.sub('isMobile', function(is) {
        mobile = is;
        paddingLeft = paddingRight = is ? 10 : 30;
        update();
    });


    return theDOM;
});

export default CardSlider;
export {CardSlider};
