package ac.essex.ooechs.music.util;

import ac.essex.ooechs.imaging.commons.util.LineEquation;
import ac.essex.ooechs.imaging.commons.Pixel;

/**
 * <p/>
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version,
 * provided that any use properly credits the author.
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details at http://www.gnu.org
 * </p>
 *
 * @author Olly Oechsle, University of Essex, Date: 06-Jul-2007
 * @version 1.0
 */
public class Staff {

    public static final int TREBLE = 1;
    public static final int BASS = 2;

    public LineEquation[] clefs;

    public int type;

    public Staff(LineEquation[] lines, int type) {
        this.clefs = lines;
        this.type = type;
    }

    public double getClosestLine(Pixel p) {
        double lowest = Integer.MAX_VALUE;
        for (int i = 0; i < clefs.length; i++) {
            LineEquation line = clefs[i];
            double dist = Math.abs(line.getY(p.x) - p.y);
            if (dist < lowest) lowest = dist;
        }
        return lowest;
    }

    public int getNote(Pixel p) {

        int line3 = (int) clefs[0].getY(p.x);
        int line5 = (int) clefs[1].getY(p.x);
        int line7 = (int) clefs[2].getY(p.x);
        int line9 = (int) clefs[3].getY(p.x);
        int line11 = (int) clefs[4].getY(p.x);

        int line1 = line3 + Math.abs(line5 - line3);
        int line13 = line11 - Math.abs(line11 - line9);

        int line2 = (line1 + line3) / 2;
        int line4 = (line3 + line5) /2;
        int line6 = (line5 + line7) /2;
        int line8 = (line7 + line9) /2;
        int line10 = (line9 + line11) /2;
        int line12 = (line11 + line13) /2;
        // TODO - filthy hack
        int line14 = line13 - 5;

        // find the most appropriate note
        int noteIndex = 0;
        double smallestDistance = Double.MAX_VALUE;

        int[] notes = new int[]{line1, line2, line3, line4, line5, line6, line7, line8, line9, line10, line11, line12, line13, line14};

        for (int i = 0; i < notes.length; i++) {
            int note = notes[i];
            int distance = Math.abs(p.y - note);
            if (distance < smallestDistance) {
                smallestDistance = distance;
                noteIndex = i;
            }
        }

        return noteIndex + 1;

    }

    public int getHeight() {
        return (int) (clefs[0].getY(0) - clefs[4].getY(0));
    }

    public String toString() {
        if (type == TREBLE) {
            return "Treble";
        } else {
            return "Bass";
        }
    }

}
