import { Assertions, Chain, FocusTools, GeneralSteps, Keyboard, Keys, Logger, Step, UiFinder } from '@ephox/agar';
import { UnitTest } from '@ephox/bedrock-client';
import { Arr } from '@ephox/katamari';
import { Attribute, Focus, SelectorFind } from '@ephox/sugar';
import * as Behaviour from 'ephox/alloy/api/behaviour/Behaviour';
import { Focusing } from 'ephox/alloy/api/behaviour/Focusing';
import { Keying } from 'ephox/alloy/api/behaviour/Keying';
import { Tabstopping } from 'ephox/alloy/api/behaviour/Tabstopping';
import * as GuiFactory from 'ephox/alloy/api/component/GuiFactory';
import * as Memento from 'ephox/alloy/api/component/Memento';
import * as GuiSetup from 'ephox/alloy/api/testhelpers/GuiSetup';
UnitTest.asynctest('Browser Test: behaviour.keying.FocusManagersTest', (success, failure) => {
    const createManager = (prefix) => {
        let active = '';
        const set = (_component, focusee) => {
            active = Attribute.get(focusee, 'class');
        };
        const get = (component) => SelectorFind.descendant(component.element, '.' + active);
        // Test only method
        const sAssert = (label, expected) => Step.sync(() => {
            Assertions.assertEq(prefix + ' ' + label, expected, active);
        });
        return {
            set,
            get,
            sAssert
        };
    };
    const makeItems = (tag, prefix, haveTabstop, firstNum) => Arr.map([firstNum, firstNum + 1, firstNum + 2], (num) => ({
        dom: {
            tag,
            classes: [prefix + '-' + num],
            innerHtml: prefix + '-' + num
        },
        behaviours: Behaviour.derive(Arr.flatten([
            [Focusing.config({})],
            haveTabstop ? [Tabstopping.config({})] : []
        ]))
    }));
    const acyclicManager = createManager('acyclic');
    const memAcyclic = Memento.record({
        dom: {
            tag: 'div',
            classes: ['acyclic']
        },
        components: makeItems('span', 'acyclic', true, 1),
        behaviours: Behaviour.derive([
            Keying.config({
                mode: 'acyclic',
                focusManager: acyclicManager
            })
        ])
    });
    const cyclicManager = createManager('cyclic');
    const memCyclic = Memento.record({
        dom: {
            tag: 'div',
            classes: ['cyclic']
        },
        components: makeItems('span', 'cyclic', true, 1),
        behaviours: Behaviour.derive([
            Keying.config({
                mode: 'cyclic',
                focusManager: cyclicManager
            })
        ])
    });
    const flatgridManager = createManager('flatgrid');
    const memFlatgrid = Memento.record({
        dom: {
            tag: 'div',
            classes: ['flatgrid']
        },
        components: makeItems('span', 'flatgrid', false, 1),
        behaviours: Behaviour.derive([
            Keying.config({
                mode: 'flatgrid',
                selector: 'span',
                initSize: {
                    numRows: 2,
                    numColumns: 2
                },
                focusManager: flatgridManager
            })
        ])
    });
    const flowManager = createManager('flow');
    const memFlow = Memento.record({
        dom: {
            tag: 'div',
            classes: ['flow']
        },
        components: makeItems('span', 'flow', false, 1),
        behaviours: Behaviour.derive([
            Keying.config({
                mode: 'flow',
                selector: 'span',
                focusManager: flowManager
            })
        ])
    });
    const matrixManager = createManager('matrix');
    const memMatrix = Memento.record({
        dom: {
            tag: 'table',
            classes: ['matrix']
        },
        components: [
            {
                dom: { tag: 'tr' },
                components: makeItems('td', 'matrix', false, 1)
            },
            {
                dom: { tag: 'tr' },
                components: makeItems('td', 'matrix', false, 4)
            }
        ],
        behaviours: Behaviour.derive([
            Keying.config({
                mode: 'matrix',
                selectors: {
                    row: 'tr',
                    cell: 'td'
                },
                focusManager: matrixManager
            })
        ])
    });
    const menuManager = createManager('menu');
    const memMenu = Memento.record({
        dom: {
            tag: 'div',
            classes: ['menu']
        },
        components: makeItems('span', 'menu', false, 1),
        behaviours: Behaviour.derive([
            Keying.config({
                mode: 'menu',
                selector: 'span',
                focusManager: menuManager
            })
        ])
    });
    GuiSetup.setup((_store, _doc, _body) => GuiFactory.build({
        dom: {
            tag: 'div',
            classes: ['container']
        },
        components: [
            memAcyclic.asSpec(),
            memCyclic.asSpec(),
            memFlatgrid.asSpec(),
            memFlow.asSpec(),
            memMatrix.asSpec(),
            memMenu.asSpec()
        ],
        behaviours: Behaviour.derive([
            Focusing.config({})
        ])
    }), (doc, _body, _gui, component, _store) => {
        const sFocusStillUnmoved = (label) => Logger.t(label, FocusTools.sTryOnSelector('Focus always stays on outer container', doc, '.container'));
        const sFocusIn = (component) => Step.sync(() => {
            Keying.focusIn(component);
        });
        const sKeyInside = (comp, selector, key, modifiers) => Chain.asStep(comp.element, [
            UiFinder.cFindIn(selector),
            Chain.op((inside) => {
                Keyboard.keydown(key, modifiers, inside);
            })
        ]);
        const acyclic = memAcyclic.get(component);
        const cyclic = memCyclic.get(component);
        const flatgrid = memFlatgrid.get(component);
        const flow = memFlow.get(component);
        const matrix = memMatrix.get(component);
        const menu = memMenu.get(component);
        const sTestKeying = (label, comp, manager, keyName) => Logger.t(label + ' Keying', GeneralSteps.sequence([
            sFocusIn(comp),
            manager.sAssert('Focus in ' + label + '-1', label + '-1'),
            sFocusStillUnmoved(label + '.focusIn'),
            // Pressing tab will work based on the get from focusManager, so it should move to acyclic-2
            sKeyInside(comp, '.' + label + '-1', Keys[keyName](), {}),
            manager.sAssert('Focus in ' + label + '-2', label + '-2'),
            sFocusStillUnmoved(label + '.' + keyName)
        ]));
        return [
            Logger.t('Initial focus on container', Step.sync(() => {
                Focus.focus(component.element);
            })),
            sTestKeying('acyclic', acyclic, acyclicManager, 'tab'),
            sTestKeying('cyclic', cyclic, cyclicManager, 'tab'),
            sTestKeying('flatgrid', flatgrid, flatgridManager, 'right'),
            sTestKeying('flow', flow, flowManager, 'right'),
            sTestKeying('matrix', matrix, matrixManager, 'right'),
            sTestKeying('menu', menu, menuManager, 'down')
        ];
    }, success, failure);
});
//# sourceMappingURL=FocusManagersTest.js.map