package com.jscape.inet.terminal.commands;

import com.jscape.inet.terminal.CellAttributes;
import com.jscape.inet.terminal.Terminal;

import java.awt.*;

/**
 * SGR -- Select Graphic Rendition.
 * Invoke the graphic rendition specified by the parameter(s).
 * All following characters transmitted to the VT100 are rendered according to
 * the parameter(s) until the next occurrence of SGR.
 */
public class SGRCommand
        implements ControlCommand {

    public static final String CANONICAL_FORM = "\033[m";
    private static final SGRCommand INSTANCE = new SGRCommand();

    //----------------------------------------------------------------------------

    /**
     * Returns one and only one instance of this type.
     *
     * @return one and only one instance of this type.
     */
    public static SGRCommand getInstance() {
        return INSTANCE;
    }

    //----------------------------------------------------------------------------

    /**
     * Private constructor to prevent uncontrolled creation.
     */
    private SGRCommand() {
    }

    //----------------------------------------------------------------------------

    /**
     * Executes command giving parameters and <code>Terminal</code> object.
     *
     * @param params   array of <code>int</code> command parametrs.
     * @param terminal target <code>Terminal</code> object.
     */
    public void execute(int[] params, Terminal terminal) {
        if (params == null || params.length == 0) {
            applyAttributes(0, terminal);
        } else {
            for (int i = 0; i < params.length; ++i) {
                applyAttributes(params[i], terminal);
            }
        }
    }

    //----------------------------------------------------------------------------

    /**
     * Sends command to remote host.
     *
     * @param params   command parameters.
     * @param terminal target <code>Terminal</code> object to send command.
     */
    public void send(int[] params, Terminal terminal) {
        if (params == null || params.length == 0) {
            terminal.send(CANONICAL_FORM);
        } else {
            StringBuffer b = new StringBuffer("\033[");

            for (int i = 0; i < params.length; ++i) {
                b.append(params[i]);
                if (i < (params.length - 1)) {
                    b.append(';');
                }
            }

            b.append('m');
            terminal.send(b.toString());
        }
    }

    //----------------------------------------------------------------------------
    private void applyAttributes(int code, Terminal terminal) {
        CellAttributes currAttr = terminal.getCellAttributes();
        boolean bold = currAttr.isBold();
        boolean underscored = currAttr.isUnderscored();
        boolean blinked = currAttr.isBlinked();
        boolean reversed = currAttr.isReversed();
        Color fg = currAttr.getFgColor();
        Color bk = currAttr.getBkColor();

        switch (code) {
            case 0:
                bold = underscored = blinked = reversed = false;
                break;
            case 1:
                bold = true;
                break;
            case 4:
                underscored = true;
                break;
            case 5:
                blinked = true;
                break;
            case 7:
                reversed = true;
                break;
            case 30:
                fg = bold ? new Color(64, 64, 64) : new Color(0, 0, 0);
                break;
            case 31:
                fg = bold ? new Color(255, 175, 175) : new Color(255, 0, 0);
                break;
            case 32:
                fg = bold ? new Color(0, 255, 190) : new Color(0, 255, 0);
                break;
            case 33:
                fg = bold ? new Color(255, 255, 0) : new Color(200, 120, 10);
                break;
            case 34:
                fg = bold ? new Color(0, 190, 255) : new Color(0, 0, 255);
                break;
            case 35:
                fg = bold ? new Color(255, 190, 255) : new Color(255, 0, 255);
                break;
            case 36:
                fg = bold ? new Color(200, 255, 255) : new Color(0, 255, 255);
                break;
            case 37:
                fg = bold ? new Color(255, 255, 255) : new Color(192, 192, 192);
                break;
            case 40:
                bk = reversed ? new Color(64, 64, 64) : new Color(0, 0, 0);
                break;
            case 41:
                bk = reversed ? new Color(255, 175, 175) : new Color(255, 0, 0);
                break;
            case 42:
                bk = reversed ? new Color(0, 255, 190) : new Color(0, 255, 0);
                break;
            case 43:
                bk =
                        reversed ? new Color(255, 255, 0) : new Color(200, 120, 10);
                break;
            case 44:
                bk = reversed ? new Color(0, 190, 255) : new Color(0, 0, 255);
                break;
            case 45:
                bk =
                        reversed
                        ? new Color(255, 190, 255)
                        : new Color(255, 0, 255);
                break;
            case 46:
                bk =
                        reversed
                        ? new Color(200, 255, 255)
                        : new Color(0, 255, 255);
                break;
            case 47:
                bk =
                        reversed
                        ? new Color(255, 255, 255)
                        : new Color(192, 192, 192);
                break;
            default:
                break;
        }

        CellAttributes newAttr =
                CellAttributes.getInstance(
                        bold,
                        underscored,
                        blinked,
                        reversed,
                        fg,
                        bk);
        terminal.setCellAttributes(newAttr);
    }

}
