import './cell.css';
import utils from 'somes';
import { React } from '.';
import { ViewController } from './ctr';
import Gesture from './gesture';
import { EventNoticer } from 'somes/event';
const transitionDuration = 500;
export class CellPanel extends Gesture {
    constructor() {
        super(...arguments);
        this._count = 0;
        this.__index = Number(this.props.index) || 0;
        this._bounce = !!Number(this.props.bounce);
        this.__preloading = Math.max(1, Number(this.props.preloading) || 1);
        this._cells = new Set();
        this.onSwitch = new EventNoticer('Switch', this);
        this._beginX = -1;
    }
    get _index() {
        return this.__index;
    }
    _reallyIndex(index) {
        var count = this._count;
        return (((index % count) + count) % count);
    }
    setIndex(index, isCall = false) {
        index = Number(index);
        var reallyIndex = this._reallyIndex(index);
        if (reallyIndex !== this._reallyIndex(this.__index) || !this.isMounted) {
            if (index > this._maxIndex || index < this._minIndex) {
                if (!isCall)
                    if (this._count < 3)
                        return;
                this.__index = reallyIndex;
            }
            else {
                this.__index = index;
            }
            utils.nextTick(() => this.forceUpdate(() => {
                for (var cell of this._cells) {
                    if (cell.index == reallyIndex) {
                        cell._resume();
                    }
                    else {
                        cell._pause();
                    }
                }
                this.onSwitch.trigger(index);
            }));
        }
    }
    get _maxIndex() {
        return this._count < 3 ? Math.max(this._count - 1, 0) : 1000;
    }
    get _minIndex() {
        return this._count < 3 ? 0 : -1000;
    }
    get _max() {
        return this._maxIndex * this.clientWidth;
    }
    get _min() {
        return this._minIndex * this.clientWidth;
    }
    _cellsDom() {
        var cells = [];
        var child = this.props.children;
        if (child) {
            cells = (Array.isArray(child) ? child : [child]);
        }
        return cells;
    }
    _preloading(count) {
        return Math.min(this.__preloading, Math.floor((count - 1) / 2));
    }
    _displayRange(index, count) {
        if (count < 3) {
            if (count == 1) {
                this.__index = 0;
                return [0];
            }
            else if (count == 2) {
                this.__index = this._reallyIndex(index);
                return [0, 1];
            }
            return [];
        }
        var preloading = this._preloading(count);
        var range = [];
        for (var i = index - preloading, j = index + preloading * 2; i < j; i++) {
            range.push(i);
        }
        return range;
    }
    _renderChild() {
        var cells = this._cellsDom();
        var count = this._count = cells.length;
        var range = this._displayRange(this._index, count);
        return range.map((index) => {
            var reallyIndex = this._reallyIndex(index);
            var cell = cells[reallyIndex];
            utils.assert(utils.equalsClass(Cell, cell.type), 'CellPanel.props.children type error');
            var key = cell.key || reallyIndex;
            var x = index * 100 + '%';
            var E = {
                ...cell,
                props: {
                    ...cell.props,
                    panel: this,
                    __index: reallyIndex,
                    key: key,
                    __left: x,
                }
            };
            return E;
        });
    }
    get transitionDuration() {
        return Number(this.props.transitionDuration) || transitionDuration;
    }
    get count() {
        return this._count;
    }
    get index() {
        return this._index;
    }
    get reallyIndex() {
        return this._reallyIndex(this._index);
    }
    set index(val) {
        this.switchAt(val);
    }
    cellAt(index) {
        for (var cell of this._cells) {
            if (cell.index == index) {
                return cell;
            }
        }
        return null;
    }
    switchAt(index, animate = true) {
        index = Number(index);
        if (this._index != index) {
            this.setIndex(index, true);
            this.refs.cells.
                style.transitionDuration = animate ? `${this.transitionDuration}ms` : '0ms';
        }
    }
    get current() {
        var cell = this.cellAt(this._index);
        utils.assert(cell);
        return cell;
    }
    render() {
        var cells = this._renderChild();
        return (React.createElement("div", { ref: "root", className: "_cells_panel " + (this.props.className ? this.props.className : '') },
            React.createElement("div", { ref: "cells", className: "_cells", style: {
                    transform: `translateX(${(-this._index) * 100}%)`,
                } }, cells)));
    }
    get $el() {
        return this.refs.root;
    }
    triggerMove(e) {
        if (e.begin_direction == 1 || e.begin_direction == 3) {
            var cells = this.refs.cells;
            if (this._beginX == -1) {
                var style = getComputedStyle(cells);
                var transformX = style.transform.split(',')[4];
                var w = this.clientWidth;
                var x = -this._index * w;
                this._beginX = parseInt(transformX);
                if (this._beginX < x - w || this._beginX > x + w) {
                    console.log('--------------', this._beginX);
                    this._beginX = x;
                }
            }
            e.cancelBubble = true;
            var move_x = e.begin_x - e.x;
            var x = move_x - this._beginX;
            if (this._bounce) {
                if (this._max < x) {
                    x -= ((x - this._max) / 1.5);
                }
                else if (x < this._min) {
                    x -= (x / 1.5);
                }
            }
            else {
                x = Math.min(this._max, x);
                x = Math.max(this._min, x);
            }
            cells.style.transform = `translateX(${-x}px)`;
            cells.style.transitionDuration = `0ms`;
        }
    }
    triggerEndMove(e) {
        if (e.begin_direction == 1 || e.begin_direction == 3) {
            if (e.speed > 100 && e.begin_direction == e.instant_direction) {
                if (e.begin_direction == 1) {
                    this.setIndex(this._index - 1);
                }
                else {
                    this.setIndex(this._index + 1);
                }
            }
            var cells = this.refs.cells;
            cells.style.transform = `translateX(${(-this._index * 100)}%)`;
            cells.style.transitionDuration = `400ms`;
            this._beginX = -1;
        }
    }
}
export class Cell extends ViewController {
    constructor(props) {
        super(props);
        this._isPause = true;
        this.onResume = new EventNoticer('Resume', this);
        this.onPause = new EventNoticer('Pause', this);
        this._panel = props.panel;
        this._panel._cells.add(this);
    }
    get index() {
        return this.props.__index;
    }
    get panel() {
        return this._panel;
    }
    get isPause() {
        return this._isPause;
    }
    triggerResume() {
        this.onResume.trigger();
    }
    triggerPause() {
        this.onPause.trigger();
    }
    _resume() {
        if (this._isPause) {
            this._isPause = false;
            this.triggerResume();
        }
    }
    _pause() {
        if (!this._isPause) {
            this._isPause = true;
            this.triggerPause();
        }
    }
    triggerMounted() {
        this._resume();
        super.triggerMounted();
    }
    triggerRemove() {
        this._panel._cells.delete(this);
        this._pause();
    }
    render() {
        var left = this.props.__left || '0';
        var style = { ...this.props.style, transform: `translateX(${left})`, position: 'absolute' };
        return (React.createElement("div", { className: `_cell ${this.props.className || ''}`, style: style }, this.renderBody() || this.props.children));
    }
    renderBody() {
        return null;
    }
}
