Source: animation/animation-types/right-angle-reverse.mjs

'use strict'

import * as td from '../../type-defs.mjs'

/**
 * @class
 * @param {td.AnimationHandler} animationHandler
 * @param {String} animName
 */
function RightAngleReverse(animationHandler, animName) {
    this.animationHandler = animationHandler
    this.name = animName

    this.ruleObject = undefined
    this.endVals = undefined
}

/**
 * @method
 * @param {td.Car} car
 */
RightAngleReverse.prototype.buildSelf = function (car) {
    this.endVals = this.getEndVals(car)

    let ruleString
    // Check if car is making an exceptional turn.
    if (car.route[0].section === car.assignedSpace.section) {
        ruleString = this.buildNormalRuleString(car, this.name, this.endVals)
    } else {
        ruleString = this.buildFarRuleString(car, this.name, this.endVals)
    }

    this.animationHandler.styleSheet.insertRule(
        ruleString,
        this.animationHandler.styleSheet.cssRules.length
    )
    this.ruleObject = this.animationHandler.getAnimationRule(this.name)
}

RightAngleReverse.prototype.buildNormalRuleString = function (
    car,
    name,
    endVals
) {
    let initial, second, last
    initial = this.buildInitialKeyframe(car)

    second = this.buildSecondKeyframe(car, endVals, 40)
    last = this.buildLastKeyframe(endVals)

    return '@keyframes ' + name + initial + second + last
}

// For cars that need to reverse farther onto other sections.
RightAngleReverse.prototype.buildFarRuleString = function (car, name, endVals) {
    let initial, second, third, last

    initial = this.buildInitialKeyframe(car)
    second = this.buildSecondKeyframe(car, endVals, 20)
    // Car finishes the actual turning partway through the anim.
    third = this.buildThirdKeyframe(car, endVals, 70)
    // Continue car backwards along road.
    endVals[car.oppSymbol] =
        car.route[0].coord + car.turningRunup * endVals.crossNegation
    if (endVals.crossNegation === -1) {
        endVals[car.oppSymbol] -= car.baseLength
    }
    last = this.buildLastKeyframe(endVals)

    return '@keyframes ' + name + initial + second + third + last
}

RightAngleReverse.prototype.buildInitialKeyframe = function (car) {
    let initial =
        '{0% {left: ' +
        car.coords.x +
        'px;top: ' +
        car.coords.y +
        'px;transform: rotate(' +
        car.orientation +
        'deg);}'
    return initial
}

RightAngleReverse.prototype.buildSecondKeyframe = function (
    car,
    endVals,
    keyframe
) {
    let leftVal, topVal, orientationVal
    switch (endVals.direction) {
        case 'west':
            // Not present
            break
        case 'east':
            if (car.direction === 'north') {
                leftVal =
                    car.coords.x + (car.assignedSpace.width - car.baseWidth) / 2
                topVal = car.coords.y + car.baseLength / 1.65
            } else if (car.direction === 'south') {
                leftVal =
                    car.coords.x + (car.assignedSpace.width - car.baseWidth) / 2
                topVal = car.coords.y - car.baseLength / 1.65
            }

            orientationVal = car.orientation + endVals.orientationMod / 6
            break
        case 'north':
            if (car.direction === 'east') {
                leftVal = car.coords.x - car.baseLength / 1.65
                topVal =
                    car.coords.y -
                    (car.assignedSpace.height - car.baseWidth) / 2
            } else if (car.direction === 'west') {
                leftVal = car.coords.x + car.baseLength / 1.65
                topVal =
                    car.coords.y -
                    (car.assignedSpace.height - car.baseWidth) / 2
            }

            orientationVal = car.orientation + endVals.orientationMod / 6
            break
        case 'south':
            if (car.direction === 'east') {
                leftVal = car.coords.x - car.baseLength / 1.65
                topVal =
                    car.coords.y +
                    (car.assignedSpace.height - car.baseWidth) / 2
            } else if (car.direction === 'west') {
                leftVal = car.coords.x + car.baseLength / 1.65
                topVal =
                    car.coords.y +
                    (car.assignedSpace.height - car.baseWidth) / 2
            }

            orientationVal = car.orientation + endVals.orientationMod / 6
            break
    }

    let second =
        keyframe +
        '% {left: ' +
        leftVal +
        'px;top: ' +
        topVal +
        'px;transform: rotate(' +
        orientationVal +
        'deg);}'
    return second
}
RightAngleReverse.prototype.buildThirdKeyframe = function (
    car,
    endVals,
    keyframe
) {
    let third =
        keyframe +
        '% {left: ' +
        endVals.x +
        'px;top: ' +
        endVals.y +
        'px;transform: rotate(' +
        endVals.orientation +
        'deg);}'
    return third
}
RightAngleReverse.prototype.buildLastKeyframe = function (endVals) {
    let last =
        '100% {left: ' +
        endVals.x +
        'px;top: ' +
        endVals.y +
        'px;transform: rotate(' +
        endVals.orientation +
        'deg);}}'
    return last
}

RightAngleReverse.prototype.getEndVals = function (car) {
    let endVals = {}

    // Should just assign endVals here?
    let relationalValues = this.getRelationalValues(car)
    endVals.orientationMod = relationalValues.orientationMod
    endVals.orientation = relationalValues.orientation
    endVals.direction = relationalValues.direction
    endVals.turnDirection = relationalValues.turnDirection
    endVals.crossNegation = relationalValues.crossNegation

    endVals[car.symbol] = car.assignedSpace.section[car.symbol]
    endVals[car.oppSymbol] = car.assignedSpace[car.oppSymbol]

    endVals = this.getAdjustedEndCoords(car, endVals)

    return endVals
}
RightAngleReverse.prototype.getRelationalValues = function (car) {
    let orientation
    let endDirection = car.route[0].direction

    let crossNegation
    switch (endDirection) {
        case 'west':
            orientation = 180
            crossNegation = 1
            break
        case 'east':
            orientation = 0
            crossNegation = -1
            break
        case 'north':
            orientation = 270
            crossNegation = 1
            break
        case 'south':
            orientation = 90
            crossNegation = -1
            break
    }

    let turnDirection = this.animationHandler.getLeftOrRight(
        car.direction,
        endDirection,
        true
    )

    let orientationMod
    if (turnDirection === 'left') {
        orientationMod = 90
    } else {
        orientationMod = -90
    }

    return {
        orientationMod: orientationMod,
        orientation: orientation,
        direction: endDirection,
        turnDirection: turnDirection,
        crossNegation: crossNegation,
    }
}
RightAngleReverse.prototype.getAdjustedEndCoords = function (car, endVals) {
    switch (endVals.direction) {
        case 'west':
            // Not present
            console.error('Car turning in unexpected/unhandled direction.')
            break
        case 'east':
            endVals.x -= car.baseLength
            endVals.x += car.assignedSpace.width / 3

            endVals.y -= (car.baseLength - car.baseWidth) / 2

            endVals.orientation = car.orientation + endVals.orientationMod
            break
        case 'north':
            endVals.x -= (car.baseLength - car.baseWidth) / 2

            endVals.y -=
                car.assignedSpace.height -
                (car.assignedSpace.height - car.baseWidth)
            endVals.y += car.baseLength
            endVals.y -= car.assignedSpace.height / 3

            endVals.orientation = car.orientation + endVals.orientationMod
            break
        case 'south':
            endVals.x -= (car.baseLength - car.baseWidth) / 2

            endVals.y -= car.baseLength
            endVals.y += car.assignedSpace.height / 3

            endVals.orientation = car.orientation + endVals.orientationMod
            break
    }

    return endVals
}

export {RightAngleReverse}