import CircuitElement from '../circuitElement';
import Node, { findNode } from '../node';
import simulationArea from '../simulationArea';
import {
    correctWidth, lineTo, moveTo, rect2,
} from '../canvasApi';

/**
 * @class
 * SquareRGBLed
 * @extends CircuitElement
 * @param {number} x - x coordinate of element.
 * @param {number} y - y coordinate of element.
 * @param {Scope=} scope - Cirucit on which element is drawn
 * @param {string=} dir - direction of element
 * @param {number=} pinLength - pins per node.
 * @category modules
 */
export default class SquareRGBLed extends CircuitElement {
    constructor(x, y, scope = globalScope, dir = 'UP', pinLength = 1) {
        super(x, y, scope, dir, 8);
        /* this is done in this.baseSetup() now
        this.scope['SquareRGBLed'].push(this);
        */
        this.rectangleObject = false;
        this.setDimensions(15, 15);
        this.pinLength = pinLength === undefined ? 1 : pinLength;
        const nodeX = -10 - 10 * pinLength;
        this.inp1 = new Node(nodeX, -10, 0, this, 8, 'R');
        this.inp2 = new Node(nodeX, 0, 0, this, 8, 'G');
        this.inp3 = new Node(nodeX, 10, 0, this, 8, 'B');
        this.inp = [this.inp1, this.inp2, this.inp3];
        this.labelDirection = 'UP';
        this.fixedBitWidth = true;

        // eslint-disable-next-line no-shadow
        this.changePinLength = function (pinLength) {
            if (pinLength === undefined) return;
            pinLength = parseInt(pinLength, 10);
            if (pinLength < 0 || pinLength > 1000) return;

            // Calculate the new position of the LED, so the nodes will stay in the same place.
            const diff = 10 * (pinLength - this.pinLength);
            // eslint-disable-next-line no-nested-ternary
            const diffX = this.direction === 'LEFT' ? -diff : this.direction === 'RIGHT' ? diff : 0;
            // eslint-disable-next-line no-nested-ternary
            const diffY = this.direction === 'UP' ? -diff : this.direction === 'DOWN' ? diff : 0;

            // Build a new LED with the new values; preserve label properties too.
            const obj = new SquareRGBLed(this.x + diffX, this.y + diffY, this.scope, this.direction, pinLength);
            obj.label = this.label;
            obj.labelDirection = this.labelDirection;

            this.cleanDelete();
            simulationArea.lastSelected = obj;
            return obj;
        };

        this.mutableProperties = {
            pinLength: {
                name: 'Pin Length',
                type: 'number',
                max: '1000',
                min: '0',
                func: 'changePinLength',
            },
        };
    }

    /**
     * @memberof SquareRGBLed
     * fn to create save Json Data of object
     * @return {JSON}
     */
    customSave() {
        const data = {
            constructorParamaters: [this.direction, this.pinLength],
            nodes: {
                inp1: findNode(this.inp1),
                inp2: findNode(this.inp2),
                inp3: findNode(this.inp3),
            },
        };
        return data;
    }

    /**
     * @memberof SquareRGBLed
     * function to draw element
     */
    customDraw() {
        const ctx = simulationArea.context;
        const xx = this.x;
        const yy = this.y;
        const r = this.inp1.value;
        const g = this.inp2.value;
        const b = this.inp3.value;

        const colors = ['rgb(174,20,20)', 'rgb(40,174,40)', 'rgb(0,100,255)'];
        for (let i = 0; i < 3; i++) {
            const x = -10 - 10 * this.pinLength;
            const y = i * 10 - 10;
            ctx.lineWidth = correctWidth(3);

            // A gray line, which makes it easy on the eyes when the pin length is large
            ctx.beginPath();
            ctx.lineCap = 'butt';
            ctx.strokeStyle = 'rgb(227, 228, 229)';
            moveTo(ctx, -15, y, xx, yy, this.direction);
            lineTo(ctx, x + 10, y, xx, yy, this.direction);
            ctx.stroke();

            // A colored line, so people know which pin does what.
            ctx.lineCap = 'round';
            ctx.beginPath();
            ctx.strokeStyle = colors[i];
            moveTo(ctx, x + 10, y, xx, yy, this.direction);
            lineTo(ctx, x, y, xx, yy, this.direction);
            ctx.stroke();
        }

        ctx.strokeStyle = '#d3d4d5';
        ctx.fillStyle = (r === undefined && g === undefined && b === undefined) ? 'rgb(227, 228, 229)' : `rgb(${r || 0}, ${g || 0}, ${b || 0})`;
        ctx.lineWidth = correctWidth(1);
        ctx.beginPath();
        rect2(ctx, -15, -15, 30, 30, xx, yy, this.direction);
        ctx.stroke();

        if ((this.hover && !simulationArea.shiftDown)
            || simulationArea.lastSelected === this
            || simulationArea.multipleObjectSelections.contains(this)) {
            ctx.fillStyle = 'rgba(255, 255, 32)';
        }

        ctx.fill();
    }
    // Draws the element in the subcuircuit. Used in layout mode
    subcircuitDraw(xOffset = 0, yOffset = 0) {
        var ctx = simulationArea.context;
        var xx = this.subcircuitMetadata.x + xOffset;
        var yy = this.subcircuitMetadata.y + yOffset;
        var r = this.inp1.value;
        var g = this.inp2.value;
        var b = this.inp3.value;

        ctx.strokeStyle = "#d3d4d5";
        ctx.fillStyle = (r === undefined && g === undefined && b === undefined) ? "rgb(227, 228, 229)" : "rgb(" + (r || 0) + ", " + (g || 0) + ", " + (b || 0) + ")";
        ctx.lineWidth = correctWidth(1);
        ctx.beginPath();
        rect2(ctx, 0, 0, 15, 15, xx, yy, this.direction);
        ctx.stroke();

        if ((this.hover && !simulationArea.shiftDown) ||
            simulationArea.lastSelected == this ||
            simulationArea.multipleObjectSelections.contains(this)) {
            ctx.fillStyle = "rgba(255, 255, 32)";
        }

        ctx.fill();
    }

    generateVerilog() {
        return this.generateVerilog.call(this);
    }
}

/**
 * @memberof SquareRGBLed
 * Help Tip
 * @type {string}
 * @category modules
 */
SquareRGBLed.prototype.tooltipText = 'Square RGB Led ToolTip: RGB Led inputs 8 bit values for the colors RED, GREEN and BLUE.';

/**
 * @memberof SquareRGBLed
 * Help URL
 * @type {string}
 * @category modules
 */
SquareRGBLed.prototype.helplink = 'https://docs.circuitverse.org/#/outputs?id=square-rgb-led';
SquareRGBLed.prototype.objectType = 'SquareRGBLed';
SquareRGBLed.prototype.canShowInSubcircuit = true;
SquareRGBLed.prototype.layoutProperties = {
    rightDimensionX : 15,
    leftDimensionX : 0,
    upDimensionY : 15,
    downDimensionY: 0
}