"use strict";
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.shouldStepBeLastStepInStepGroup = exports.isStepFirstStepInStepGroup = exports.isModulator = exports.isTraversalSource = void 0;
const types_1 = require("../../../types");
const consts_1 = require("../../../consts");
const layoutUtils_1 = require("../../../layoutUtils");
const isTraversalSource = (step) => {
    return step.type === types_1.TokenType.Word && step.word === 'g';
};
exports.isTraversalSource = isTraversalSource;
const isModulator = (step) => {
    if (step.type !== types_1.TokenType.Method && step.type !== types_1.TokenType.Closure)
        return false;
    if (step.method.type !== types_1.TokenType.Word)
        return false;
    return consts_1.STEP_MODULATORS.includes(step.method.word);
};
exports.isModulator = isModulator;
const isStepFirstStepInStepGroup = ({ stepsInStepGroup }) => {
    return !stepsInStepGroup.length;
};
exports.isStepFirstStepInStepGroup = isStepFirstStepInStepGroup;
const isLineTooLongWithSubsequentModulators = (config) => ({ stepsInStepGroup, stepGroups, }, step, index, steps) => {
    const stepsWithSubsequentModulators = steps.slice(index + 1).reduce((aggregator, step) => {
        const { stepsInStepGroup, hasReachedFinalModulator } = aggregator;
        if (hasReachedFinalModulator)
            return aggregator;
        if ((0, exports.isModulator)(step)) {
            return {
                ...aggregator,
                stepsInStepGroup: [...stepsInStepGroup, step],
            };
        }
        return { ...aggregator, hasReachedFinalModulator: true };
    }, {
        stepsInStepGroup: [...stepsInStepGroup, step],
        hasReachedFinalModulator: false,
    }).stepsInStepGroup;
    const stepGroupIndentationIncrease = (() => {
        const traversalSourceIndentationIncrease = stepGroups[0] && (0, exports.isTraversalSource)(stepGroups[0].steps[0]) ? 2 : 0;
        const modulatorIndentationIncrease = (0, exports.isModulator)([...stepsInStepGroup, step][0]) ? 2 : 0;
        const indentationIncrease = traversalSourceIndentationIncrease + modulatorIndentationIncrease;
        return indentationIncrease;
    })();
    return !(0, layoutUtils_1.willFitOnLine)({
        type: types_1.TokenType.Traversal,
        steps: stepsWithSubsequentModulators,
    }, config, config.horizontalPosition + stepGroupIndentationIncrease);
};
// If the first step in a group is a modulator, then it must also be the last step in the group
const shouldStepBeLastStepInStepGroup = (config) => ({ stepsInStepGroup, stepGroups, }, step, index, steps) => {
    const isFirstStepInStepGroup = !stepsInStepGroup.length;
    const isLastStep = index === steps.length - 1;
    const nextStepIsModulator = !isLastStep && (0, exports.isModulator)(steps[index + 1]);
    const lineIsTooLongWithSubsequentModulators = isLineTooLongWithSubsequentModulators(config)({ stepsInStepGroup, stepGroups }, step, index, steps);
    // If the first step in a group is a modulator, then it must also be the last step in the group
    const stepShouldBeLastStepInStepGroup = isLastStep ||
        (isFirstStepInStepGroup && (0, exports.isModulator)(step)) ||
        ((step.type === types_1.TokenType.Method || step.type === types_1.TokenType.Closure) &&
            !(nextStepIsModulator && !lineIsTooLongWithSubsequentModulators));
    return stepShouldBeLastStepInStepGroup;
};
exports.shouldStepBeLastStepInStepGroup = shouldStepBeLastStepInStepGroup;
