/**
 * @fileoverview A class to operate forking.
 *
 * This is state of forking.
 * This has a fork list and manages it.
 *
 * @author Toru Nagashima
 */

"use strict";

//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------

const assert = require("assert"),
    CodePathSegment = require("./code-path-segment");

//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------

/**
 * Gets whether or not a given segment is reachable.
 *
 * @param {CodePathSegment} segment - A segment to get.
 * @returns {boolean} `true` if the segment is reachable.
 */
function isReachable(segment) {
    return segment.reachable;
}

/**
 * Creates new segments from the specific range of `context.segmentsList`.
 *
 * When `context.segmentsList` is `[[a, b], [c, d], [e, f]]`, `begin` is `0`, and
 * `end` is `-1`, this creates `[g, h]`. This `g` is from `a`, `c`, and `e`.
 * This `h` is from `b`, `d`, and `f`.
 *
 * @param {ForkContext} context - An instance.
 * @param {number} begin - The first index of the previous segments.
 * @param {number} end - The last index of the previous segments.
 * @param {Function} create - A factory function of new segments.
 * @returns {CodePathSegment[]} New segments.
 */
function makeSegments(context, begin, end, create) {
    const list = context.segmentsList;

    const normalizedBegin = begin >= 0 ? begin : list.length + begin;
    const normalizedEnd = end >= 0 ? end : list.length + end;

    const segments = [];

    for (let i = 0; i < context.count; ++i) {
        const allPrevSegments = [];

        for (let j = normalizedBegin; j <= normalizedEnd; ++j) {
            allPrevSegments.push(list[j][i]);
        }

        segments.push(create(context.idGenerator.next(), allPrevSegments));
    }

    return segments;
}

/**
 * `segments` becomes doubly in a `finally` block. Then if a code path exits by a
 * control statement (such as `break`, `continue`) from the `finally` block, the
 * destination's segments may be half of the source segments. In that case, this
 * merges segments.
 *
 * @param {ForkContext} context - An instance.
 * @param {CodePathSegment[]} segments - Segments to merge.
 * @returns {CodePathSegment[]} The merged segments.
 */
function mergeExtraSegments(context, segments) {
    let currentSegments = segments;

    while (currentSegments.length > context.count) {
        const merged = [];

        for (let i = 0, length = currentSegments.length / 2 | 0; i < length; ++i) {
            merged.push(CodePathSegment.newNext(
                context.idGenerator.next(),
                [currentSegments[i], currentSegments[i + length]]
            ));
        }
        currentSegments = merged;
    }
    return currentSegments;
}

//------------------------------------------------------------------------------
// Public Interface
//------------------------------------------------------------------------------

/**
 * A class to manage forking.
 */
class ForkContext {

    /**
     * @param {IdGenerator} idGenerator - An identifier generator for segments.
     * @param {ForkContext|null} upper - An upper fork context.
     * @param {number} count - A number of parallel segments.
     */
    constructor(idGenerator, upper, count) {
        this.idGenerator = idGenerator;
        this.upper = upper;
        this.count = count;
        this.segmentsList = [];
    }

    /**
     * The head segments.
     * @type {CodePathSegment[]}
     */
    get head() {
        const list = this.segmentsList;

        return list.length === 0 ? [] : list[list.length - 1];
    }

    /**
     * A flag which shows empty.
     * @type {boolean}
     */
    get empty() {
        return this.segmentsList.length === 0;
    }

    /**
     * A flag which shows reachable.
     * @type {boolean}
     */
    get reachable() {
        const segments = this.head;

        return segments.length > 0 && segments.some(isReachable);
    }

    /**
     * Creates new segments from this context.
     *
     * @param {number} begin - The first index of previous segments.
     * @param {number} end - The last index of previous segments.
     * @returns {CodePathSegment[]} New segments.
     */
    makeNext(begin, end) {
        return makeSegments(this, begin, end, CodePathSegment.newNext);
    }

    /**
     * Creates new segments from this context.
     * The new segments is always unreachable.
     *
     * @param {number} begin - The first index of previous segments.
     * @param {number} end - The last index of previous segments.
     * @returns {CodePathSegment[]} New segments.
     */
    makeUnreachable(begin, end) {
        return makeSegments(this, begin, end, CodePathSegment.newUnreachable);
    }

    /**
     * Creates new segments from this context.
     * The new segments don't have connections for previous segments.
     * But these inherit the reachable flag from this context.
     *
     * @param {number} begin - The first index of previous segments.
     * @param {number} end - The last index of previous segments.
     * @returns {CodePathSegment[]} New segments.
     */
    makeDisconnected(begin, end) {
        return makeSegments(this, begin, end, CodePathSegment.newDisconnected);
    }

    /**
     * Adds segments into this context.
     * The added segments become the head.
     *
     * @param {CodePathSegment[]} segments - Segments to add.
     * @returns {void}
     */
    add(segments) {
        assert(segments.length >= this.count, `${segments.length} >= ${this.count}`);

        this.segmentsList.push(mergeExtraSegments(this, segments));
    }

    /**
     * Replaces the head segments with given segments.
     * The current head segments are removed.
     *
     * @param {CodePathSegment[]} segments - Segments to add.
     * @returns {void}
     */
    replaceHead(segments) {
        assert(segments.length >= this.count, `${segments.length} >= ${this.count}`);

        this.segmentsList.splice(-1, 1, mergeExtraSegments(this, segments));
    }

    /**
     * Adds all segments of a given fork context into this context.
     *
     * @param {ForkContext} context - A fork context to add.
     * @returns {void}
     */
    addAll(context) {
        assert(context.count === this.count);

        const source = context.segmentsList;

        for (let i = 0; i < source.length; ++i) {
            this.segmentsList.push(source[i]);
        }
    }

    /**
     * Clears all secments in this context.
     *
     * @returns {void}
     */
    clear() {
        this.segmentsList = [];
    }

    /**
     * Creates the root fork context.
     *
     * @param {IdGenerator} idGenerator - An identifier generator for segments.
     * @returns {ForkContext} New fork context.
     */
    static newRoot(idGenerator) {
        const context = new ForkContext(idGenerator, null, 1);

        context.add([CodePathSegment.newRoot(idGenerator.next())]);

        return context;
    }

    /**
     * Creates an empty fork context preceded by a given context.
     *
     * @param {ForkContext} parentContext - The parent fork context.
     * @param {boolean} forkLeavingPath - A flag which shows inside of `finally` block.
     * @returns {ForkContext} New fork context.
     */
    static newEmpty(parentContext, forkLeavingPath) {
        return new ForkContext(
            parentContext.idGenerator,
            parentContext,
            (forkLeavingPath ? 2 : 1) * parentContext.count
        );
    }
}

module.exports = ForkContext;
