package vermilion;

//TODO: Implement keyboard mappings (e.g. for different locales) when programming
//musical notes in the tracker interface. (I8LN. "I Hate LaNguages"  :-P )

import java.awt.event.KeyEvent;

/**
 * A tracker column that represents a continuous slider control as a four
 * digit number.
 */
public class JTrackerColumnNote extends JTrackerColumn
{
    // The names of notes as displayed on the screen, just like oldsk0ol trackers.
    private static final String[] noteNames = new String[]
        { "A-", "A#", "B-", "C-", "C#", "D-", "D#", "E-", "F-", "F#", "G-", "G#"  };

    // The keys mapped as notes, in order. TODO: Proper multioctave (beyond m key).
    private static final char[] noteKeys = new char[]
        { 'z', 's', 'x', 'd', 'c', 'v', 'g', 'b', 'h', 'n', 'j', 'm',
          'q', '2', 'w', '3', 'e', 'r', '5', 't', '6', 'y', '7', 'u', 'i' };

    // The octave currently used as the offset for notes, which is adjusted
    // with
    private int currOctave = 6;

    /**
     * Constructs a new column for representing a note parameter.
     */
    public JTrackerColumnNote(String colName, String paramName, PatternNode pattern, PatternTrackNode commands, int trackNumber)
    {
        super(colName, paramName, pattern, 6, commands, trackNumber);
    }

    /**
     * Gets note value entries from the pattern for display.
     */
    @Override
    public String getEntry(int rowNum)
    {
        ParameterNote command = (ParameterNote) commandList.commands.get(rowNum);

        if (command != null)
        {
            int noteValue = command.value;
            int fineTune = noteValue % 100;
            int noteNum = noteValue / 100;

            int noteNote = noteNum % 12;
            int noteOct = noteNum / 12;

            String noteVal = noteNames[noteNote];
            String octVal = String.valueOf(noteOct);
            if (octVal.length() < 2) octVal = "0" + octVal;
            noteVal += octVal;

            octVal = String.valueOf(fineTune);
            if (octVal.length() < 2) octVal = "0" + octVal;
            noteVal += octVal;

            return noteVal;
        }
        else return "------";
    }

    /**
     * Interprets keypresses and creates or modifies note cues.
     */
    @Override
    public boolean setEntry(int rowNum, int cursorPos, KeyEvent key)
    {
        if (key.getKeyCode() == KeyEvent.VK_BACK_SPACE ||
            key.getKeyCode() == KeyEvent.VK_DELETE)
        {
            commandList.commands.remove(rowNum);
            return true;
        }

        char keyChar = key.getKeyChar();

        if (keyChar == '-' || keyChar == '_')
        {
            currOctave--;
            if (currOctave < 0) currOctave = 0;
            return false;
        }

        if (keyChar == '=' || keyChar == '+')
        {
            currOctave++;
            if (currOctave > 10) currOctave = 10;
            return false;
        }

        if (cursorPos > 1)
        {
            if (keyChar >= '0' && keyChar <= '9')
            {
                ParameterNote note = (ParameterNote) commandList.commands.get(rowNum);
                if (note != null)
                {
                    if (cursorPos > 3)
                    {
                        int tuneVal = note.value % 100;
                        int noteVal = note.value / 100;

                        // TODO: Make this a function and use in getVal
                        String tuneStr = String.valueOf(tuneVal);
                        if (tuneStr.length() < 2) tuneStr = "0" + tuneStr;
                        System.out.println(tuneStr);

                        char[] octChars = tuneStr.toCharArray();
                        if (cursorPos == 4) octChars[0] = keyChar;
                        else if (cursorPos == 5) octChars[1] = keyChar;

                        tuneStr = new String(octChars);
                        System.out.println(tuneStr);
                        tuneVal = Integer.parseInt(tuneStr);

                        note.value = noteVal * 100 + tuneVal;
                        return true;
                    }
                    else
                    {
                        int octVal = note.value / 1200;
                        int noteVal = note.value % 1200;

                        // TODO: Make this a function and use in getVal
                        String octStr = String.valueOf(octVal);
                        if (octStr.length() < 2) octStr = "0" + octStr;
                        System.out.println(octStr);

                        char[] octChars = octStr.toCharArray();
                        if (cursorPos == 2) octChars[0] = keyChar;
                        else if (cursorPos == 3) octChars[1] = keyChar;

                        octStr = new String(octChars);
                        System.out.println(octStr);
                        octVal = Integer.parseInt(octStr);

                        if (octVal < 12)
                        {
                            note.value = octVal * 1200 + noteVal;
                            return true;
                        }
                        return false;
                    }
                }
            }
        }

        int noteVal = -1;
        for (int x = 0; x < noteKeys.length; x++)
        {
            if (keyChar == noteKeys[x]) noteVal = x;
        }
        if (noteVal < 0) return false;

        ParameterNote newNode = new ParameterNote(ParameterNote.NOTE_OFF);
        newNode.value = (noteVal+3 + currOctave*12)*100;
        commandList.commands.put(rowNum, newNode);

        return true;
    }

    /**
     * Returns a helper/info display message for the current column, cursor
     * position and cue if one exists.
     */
    @Override
    public String getCursorDescription(int rowNum, int cursorPos)
    {
        // TODO: Description of entry if any, cursor pos.
        if (cursorPos > 3)
        {
            return "'" + parameterName + "' Finetune - Keys 1, 2, 3, 4...";
        }
        else if (cursorPos > 1)
        {
            return "'" + parameterName + "' Octave - Keys 1, 2, 3, 4...";
        }
        else
        {
            return "'" + parameterName + "' Notes - Keys z, s, x, d, c, v... - Octave Up/Down -/= or _/+";
        }
    }
}

