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);
};
import { handleActions } from 'redux-actions';
import config from '../../config/threed';
import * as actions from '../../actions/threed';
import Scene from '../../lib/object3dts/Scene';
export var findObject = function (objects, fn) {
    if (objects === void 0) { objects = []; }
    if (!objects.length)
        return undefined;
    var first = objects[0], rest = objects.slice(1);
    if (fn(first))
        return first;
    return findObject(first.children, fn) || findObject(rest, fn);
};
var createObjectName = function (base, objects) {
    var name = base;
    var nameIndex = 1;
    while (findObject(objects, function (object) { return object.viewOptions.name === name; })) {
        nameIndex++;
        name = base + nameIndex;
    }
    return name;
};
var initialState = {
    sceneInstance: new Scene(),
    objects: [],
};
var scene = handleActions(new Map([
    [
        actions.createObject,
        function (state, _a) {
            var payload = _a.payload;
            var sceneInstance = state.sceneInstance, objects = state.objects;
            var newObject = __assign({}, payload, { viewOptions: {
                    color: config.colors[Math.floor(Math.random() * config.colors.length)],
                    name: createObjectName(payload.type, objects),
                } });
            return __assign({}, state, { objects: state.sceneInstance.addNewObjectFromJSON(newObject) });
        },
    ],
    [
        actions.updateObjectViewOption,
        function (state, _a) {
            var _b = _a.payload, object = _b.object, option = _b.option, value = _b.value;
            var _c;
            var updatedObject = __assign({}, object, { viewOptions: __assign({}, object.viewOptions, (_c = {}, _c[option] = value, _c)) });
            return __assign({}, state, { objects: state.sceneInstance.updateObject(updatedObject) });
        },
    ],
    [
        actions.updateObjectParameter,
        function (state, _a) {
            var _b = _a.payload, object = _b.object, parameter = _b.parameter, value = _b.value;
            var _c;
            var updatedObject = __assign({}, object, { parameters: __assign({}, object.parameters, (_c = {}, _c[parameter] = value, _c)) });
            return __assign({}, state, { objects: state.sceneInstance.updateObject(updatedObject) });
        },
    ],
    [
        actions.updateObject,
        function (state, _a) {
            var payload = _a.payload;
            return (__assign({}, state, { objects: state.sceneInstance.updateObject(payload) }));
        }
    ],
    [
        actions.updateOperation,
        function (state, _a) {
            var _b = _a.payload, object = _b.object, operation = _b.operation;
            return (__assign({}, state, { objects: state.sceneInstance.updateObject(__assign({}, object, { operations: object.operations.map(function (o) { return (o.id === operation.id ? operation : o); }) })) }));
        },
    ],
    [
        actions.duplicateObject,
        function (state, _a) {
            var payload = _a.payload;
            return (__assign({}, state, { objects: state.sceneInstance.cloneOject(__assign({}, payload, { viewOptions: __assign({}, payload.viewOptions, { name: createObjectName(payload.viewOptions.name, state.objects) }) })) }));
        },
    ],
    [
        actions.addOperation,
        function (state, _a) {
            var _b = _a.payload, object = _b.object, operation = _b.operation;
            return (__assign({}, state, { objects: state.sceneInstance.updateObject(__assign({}, object, { operations: object.operations.concat([operation]) })) }));
        },
    ],
    [
        actions.removeOperation,
        function (state, _a) {
            var _b = _a.payload, object = _b.object, operation = _b.operation;
            return (__assign({}, state, { objects: state.sceneInstance.updateObject(__assign({}, object, { operations: object.operations.filter(function (op) { return op !== operation; }) })) }));
        },
    ],
    [
        actions.reorderOperation,
        function (state, _a) {
            var _b = _a.payload, object = _b.object, operation = _b.operation, from = _b.from, to = _b.to;
            var operations = object.operations.slice();
            operations.splice(from, 1);
            operations.splice(to, 0, operation);
            return __assign({}, state, { objects: state.sceneInstance.updateObject(__assign({}, object, { operations: operations })) });
        },
    ],
    [
        actions.deleteObject,
        function (state, _a) {
            var payload = _a.payload;
            return (__assign({}, state, { objects: state.sceneInstance.removeFromScene(payload) }));
        },
    ],
    [
        actions.undoComposition,
        function (state, _a) {
            var payload = _a.payload;
            return (__assign({}, state, { objects: state.sceneInstance.undoCompound(payload) }));
        },
    ],
    [
        actions.ungroup,
        function (state, _a) {
            var payload = _a.payload;
            return (__assign({}, state, { objects: state.sceneInstance.unGroup(payload) }));
        },
    ],
    [
        actions.convertToGroup,
        function (state, _a) {
            var payload = _a.payload;
            return (__assign({}, state, { objects: state.sceneInstance.convertToGroup(payload) }));
        },
    ]
]), initialState);
export default scene;
//# sourceMappingURL=scene.js.map