"use strict";
var __assign = (this && this.__assign) || function () {
    __assign = Object.assign || function(t) {
        for (var s, i = 1, n = arguments.length; i < n; i++) {
            s = arguments[i];
            for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
                t[p] = s[p];
        }
        return t;
    };
    return __assign.apply(this, arguments);
};
var __read = (this && this.__read) || function (o, n) {
    var m = typeof Symbol === "function" && o[Symbol.iterator];
    if (!m) return o;
    var i = m.call(o), r, ar = [], e;
    try {
        while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
    }
    catch (error) { e = { error: error }; }
    finally {
        try {
            if (r && !r.done && (m = i["return"])) m.call(i);
        }
        finally { if (e) throw e.error; }
    }
    return ar;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.PaletteView = void 0;
var csstips = require("csstips/lib");
var React = require("react");
var recoil_1 = require("recoil");
var lib_1 = require("typestyle/lib");
var ExpandLess_1 = require("../icons/ExpandLess");
var recoils_1 = require("../recoils");
var colors_1 = require("../utils/colors");
var shallowEqual_1 = require("../utils/shallowEqual");
var ErrorBoundary_1 = require("./ErrorBoundary");
var IconButton_1 = require("./IconButton");
var Paper_1 = require("./Paper");
var transparent = 'rgba(255,255,255,0)';
var tileSize = 32;
var floatThrethold = 300;
var cn = {
    root: lib_1.style(csstips.flex1, csstips.vertical, {
        margin: 16,
        marginTop: 0,
        flexBasis: floatThrethold,
        height: '100%',
        position: 'relative',
        overflow: 'hidden'
    }),
    expandLessWrapper: lib_1.style({
        width: '100%',
        marginTop: 8,
        textAlign: 'center'
    }),
    table: lib_1.style({
        flex: 1,
        overflowY: 'scroll',
        overflowX: 'hidden',
        boxSizing: 'content-box',
        paddingRight: 10,
        $nest: {
            '&>img': {
                boxSizing: 'border-box',
                cursor: 'copy',
                borderWidth: 0.5,
                borderStyle: 'solid',
                borderColor: 'transparent',
                width: '12.5%',
                height: 'auto',
                marginBottom: -3 // うまく height が計算されない？列方向に謎の空白が生まれる
            },
            '&>img.selected': {
                borderColor: colors_1.colors.selected
            },
            '&::-webkit-scrollbar': {
                width: 10
            },
            '&::-webkit-scrollbar-track': {
                borderRadius: 4,
                backgroundColor: 'rgb(255,255,255)'
            },
            '&::-webkit-scrollbar-thumb': {
                borderRadius: 4,
                backgroundColor: 'rgb(62,62,62)'
            }
        }
    }),
    pageView: lib_1.style({
        marginBottom: 4
    }),
    paletteWrapper: lib_1.style({
        position: 'relative'
    })
};
function PaletteView() {
    return (React.createElement("div", { className: cn.root },
        React.createElement(ErrorBoundary_1.ErrorBoundary, null,
            React.createElement(React.Suspense, { fallback: "Loading..." },
                React.createElement(TileSetsView, null)))));
}
exports.PaletteView = PaletteView;
function TileSetsView() {
    var pages = recoil_1.useRecoilValue(recoils_1.palettePagesState);
    return React.useMemo(function () { return (React.createElement("div", { className: cn.table }, pages.map(function (page) { return (React.createElement(PageView, __assign({ key: page.index }, page))); }))); }, [pages]);
}
function PageView(props) {
    var _a = __read(React.useState(props.row > 1), 2), collapsed = _a[0], setCollapsed = _a[1];
    var setSelection = recoil_1.useSetRecoilState(recoils_1.paletteSelectionState);
    var setBaseSelection = recoil_1.useSetRecoilState(recoils_1.baseSelectionState);
    var _b = __read(recoil_1.useRecoilState(recoils_1.cursorModeState), 2), cursorMode = _b[0], setCursorMode = _b[1];
    var touchRef = React.useRef(0); // save last touch indentifier of onTouchStart
    var draggingRef = React.useRef(false); // is dragging or swiping?
    var release = React.useCallback(function () {
        draggingRef.current = false;
    }, []);
    React.useEffect(function () {
        window.addEventListener('mouseup', release, { passive: true });
        window.addEventListener('touchend', release, { passive: true });
        return function () {
            window.removeEventListener('mouseup', release);
            window.removeEventListener('touchend', release);
        };
    }, [release]);
    var canOpen = props.row > 1 && collapsed;
    var open = React.useCallback(function () {
        if (canOpen) {
            setCollapsed(false);
        }
    }, [canOpen]);
    var canClose = props.row > 1 && !collapsed;
    var close = React.useCallback(function () {
        if (canClose) {
            setCollapsed(true);
        }
    }, [canClose]);
    var start = React.useCallback(function (pos) {
        if (pos.row >= props.row)
            return; // 超過している
        var selection = {
            page: props.index,
            start: pos,
            end: pos
        };
        if (cursorMode === 'base') {
            // base の場合は sceneMap を変更する
            setBaseSelection(selection);
        }
        else {
            // それ以外の場合は nib として選ぶ
            draggingRef.current = true;
            setSelection(selection);
            setCursorMode('pen');
        }
    }, [cursorMode]);
    var move = React.useCallback(function (pos) {
        if (!draggingRef.current)
            return;
        setSelection(function (selection) {
            if (!selection)
                return selection;
            if (shallowEqual_1.shallowEqual(pos, selection.end))
                return selection;
            if (pos.row >= props.row)
                return selection; // 超過している
            return {
                page: selection.page,
                start: selection.start,
                end: pos
            };
        });
    }, []);
    var handleMouseDown = React.useCallback(function (e) {
        if (collapsed)
            return;
        start(getPos(e.clientX, e.clientY, e.currentTarget.getBoundingClientRect()));
    }, [collapsed, start]);
    var handleMouseMove = React.useCallback(function (e) {
        if (collapsed)
            return;
        move(getPos(e.clientX, e.clientY, e.currentTarget.getBoundingClientRect()));
    }, [collapsed, move]);
    var handleTouchStart = React.useCallback(function (e) {
        var p = e.touches.item(0);
        if (collapsed || !p)
            return;
        start(getPos(p.clientX, p.clientY, e.currentTarget.getBoundingClientRect()));
        touchRef.current = p.identifier;
    }, [collapsed, start]);
    var handleTouchMove = React.useCallback(function (e) {
        var p = e.touches.item(0);
        if (collapsed || !p || p.identifier !== touchRef.current)
            return;
        move(getPos(p.clientX, p.clientY, e.currentTarget.getBoundingClientRect()));
    }, [collapsed, move]);
    return (React.createElement("div", { className: cn.pageView },
        React.createElement(Paper_1.Paper, { id: "rme-palette-view", style: {
                padding: 4,
                paddingBottom: collapsed ? 0 : 4,
                cursor: canOpen ? 'pointer' : 'inherit',
                width: tileSize * 8,
                boxSizing: 'content-box'
            }, onClick: open },
            React.createElement("div", { className: cn.paletteWrapper, onMouseDown: handleMouseDown, onMouseMove: handleMouseMove, onMouseUp: release, onTouchStart: handleTouchStart, onTouchMove: handleTouchMove, onTouchEnd: release },
                React.createElement("div", { style: {
                        height: collapsed ? tileSize : tileSize * props.row,
                        overflow: 'hidden',
                        position: 'relative',
                        transition: 'height 200ms'
                    } },
                    React.createElement("img", { src: props.src, alt: "", style: {
                            position: 'absolute',
                            top: 0,
                            left: 0,
                            width: tileSize * 8,
                            touchAction: 'none',
                            transformOrigin: 'top',
                            transform: collapsed ? 'scaleY(0.5)' : 'none'
                        }, draggable: false })),
                collapsed ? null : React.createElement(SelectionView, { page: props.index }),
                collapsed ? (React.createElement("div", { style: {
                        position: 'absolute',
                        background: "linear-gradient(" + transparent + "," + transparent + "," + colors_1.colors.paper + ")",
                        height: '100%',
                        width: '100%',
                        top: 0,
                        zIndex: 1
                    } })) : null),
            canClose ? (React.createElement(IconButton_1.IconButton, { className: cn.expandLessWrapper, onClick: close },
                React.createElement(ExpandLess_1.default, null))) : null)));
}
function SelectionView(_a) {
    var page = _a.page;
    var nibSelection = recoil_1.useRecoilValue(recoils_1.paletteSelectionState);
    var baseSelection = recoil_1.useRecoilValue(recoils_1.baseSelectionState);
    var preloaded = recoil_1.useRecoilValueLoadable(recoils_1.preloadNibState);
    var cursorMode = recoil_1.useRecoilValue(recoils_1.cursorModeState);
    var selection = cursorMode === 'base' ? baseSelection : nibSelection;
    if (!selection || selection.page !== page)
        return null;
    var start = selection.start, end = selection.end;
    return (React.createElement(Rect, { left: Math.min(start.col, end.col), top: Math.min(start.row, end.row), right: Math.max(start.col, end.col) + 1, bottom: Math.max(start.row, end.row) + 1, cursor: preloaded.state === 'loading'
            ? 'progress'
            : preloaded.state === 'hasError'
                ? 'not-allowed'
                : 'initial' }));
}
function Rect(_a) {
    var left = _a.left, top = _a.top, right = _a.right, bottom = _a.bottom, cursor = _a.cursor;
    var borderWidth = 2;
    return (React.createElement("div", { style: {
            cursor: cursor,
            borderWidth: borderWidth,
            borderStyle: 'solid',
            borderColor: colors_1.colors.selected,
            boxSizing: 'border-box',
            position: 'absolute',
            left: left * tileSize - borderWidth + "px",
            top: top * tileSize - borderWidth + "px",
            width: (right - left) * tileSize + borderWidth * 2 + "px",
            height: (bottom - top) * tileSize + borderWidth * 2 + "px",
            zIndex: 1
        } }));
}
function getPos(x, y, bound) {
    var tileSize = bound.width / 8;
    var col = Math.max(0, (x - bound.left) / tileSize) | 0;
    var row = Math.max(0, (y - bound.top) / tileSize) | 0;
    return {
        row: row,
        col: col,
        num: col + row * 8
    };
}
//# sourceMappingURL=PaletteView.js.map