using UnityEngine;
using System.Collections;
using System;
using System.Collections.Generic;

public class OctaveSensor : MonoBehaviour {

    public int curOctave = 0;
    public int iCurNote = 0;

    private float[,] octaveRanges = new float[ , ] { { 0f, 0f }, { 0f, 0f }, { 65f, 123f }, { 131f, 247f }, { 262f, 493f }, { 523f, 988f }, { 1047f, 1976f }, { 2093f, 3951f } };

    private float[][] octaves =     {
            new float[] { 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f },
            new float[] { 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f },
            new float[] { 65f, 69f, 73f, 78f, 82f, 87f, 93f, 98f, 104f, 110f, 117f, 123f },
            new float[] { 131, 139, 147, 156, 165, 175, 185, 196, 208, 220, 233, 247 },
            new float[] { 262, 277, 294, 311, 330, 349, 370, 392, 415, 440, 466, 493 },
            new float[] { 523, 554, 587, 622, 659, 698, 740, 784, 831, 880, 932, 988 },
            new float[] { 1047, 1109, 1175, 1245, 1319, 1397, 1480, 1568, 1661, 1760, 1864, 1976 },
            new float[] { 2093, 2217, 2349, 2489, 2637, 2794, 2960, 3136, 3322, 3520, 3729, 3951 },
    };


    private string[] notes = { "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B" };


    public int getOctaveFromTone(float tone)
    {
        curOctave = 0;

        int octavesLen = octaveRanges.GetLength(0);

        for (int i = 0; i < octavesLen; i++) 
        {

            if (tone > octaveRanges[i, 0] && tone < octaveRanges[i, 1])
            {
                curOctave = i;
            }
        }

        return curOctave;
    }

    public string getNoteFromTone(float tone)
    {
        string note = "A";

        int thisOct = getOctaveFromTone(tone);

        int index = Array.BinarySearch(octaves[thisOct], tone);


        if (index < 0)
        {

            int firstInd;
            int secondInd;

            // If the index is negative, it represents the bitwise
            // complement of the next larger element in the array.
            //
            index = ~index;

            //gets the two notes _around_ what the user has sung
            if (index == 0)
                firstInd = 0;
            else
                firstInd = index - 1;

            if (index == octaves[thisOct].Length)
                secondInd = octaves[thisOct].Length - 1;
            else
                secondInd = index;

            //get differences
            float diffLower = tone - octaves[thisOct][firstInd];
            float diffHigher = octaves[thisOct][secondInd] - tone;

            //decide on the closest 'winner'
            if (diffLower > diffHigher)
            {
                note = notes[firstInd];
                iCurNote = firstInd;
            }  
            else
            {
                note = notes[secondInd];
                iCurNote = secondInd;
            }
        }
        else
        {
            //fits note _exactly_
            note = notes[index];
            //for future
            iCurNote = index;
        }

   

        return note;
    }

    /*
    public int[] getOctaveRange(int oct)
    {
        return octaveRanges[oct];
    }
    */
}
