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

namespace Core
{
    class Level
    {
        private Queue<Note> notes = new Queue<Note>();

        public void AddNote(Note note)
        {
            notes.Enqueue(note);
        }

        void HandleInput()
        {

        }

        void UpdateNotes()
        {

        }
    }

    abstract class Note
    {
        // define common note properties

        public double Time;
        public HandType HandType;

        protected GameObject gameObject;
        
        // interpret note option
        protected abstract void FromBmsNum(String num);
        protected abstract GameObject CreateGameObjectImpl();

        // instantiate associated game object

        public void CreateGameObject()
        {
            gameObject = CreateGameObjectImpl();
        }

        // factory method
        // may return null if given note is not supported
        public static Note Create(BmsNote bn, double bpm)
        {
            Note note = null;
            HandType handType = HandType.None;

            Debug.Log(String.Format("{0}, {1}, {2}", bn.barTime, bn.lane, bn.num));

            switch (bn.lane)
            {
                case "11": // 1p first lane: FORWARD LEFT HAND
                    note = new ForwardNote();
                    handType = HandType.Left;
                    break;
                case "12": // 1p second lane: FORWARD RIGHT HAND
                    note = new ForwardNote();
                    handType = HandType.Right;
                    break;
                //case "13": // 1p third lane: REAR LEFT HAND
                //    handType = HandType.Left;

                //    break;
                //case "14": // 1p forth lane: REAR RIGHT HAND
                //    handType = HandType.Right;

                //    break;
                //case "15": // 1p fifth lane: EDGE LEFT HAND
                //    handType = HandType.Left;

                //    break;
                //case "16": // 1p sixth lane: EDGE RIGHT HAND
                //    handType = HandType.Right;

                //    break;

                // add action notes 

                default:
                    return null;
            }

            note.FromBmsNum(bn.num);
            note.HandType = handType;
            note.Time = bn.barTime * (60.0 / bpm * 4);

            return note;
        }
    }

    class ForwardNote : Note
    {
        private float x, y;

        protected override GameObject CreateGameObjectImpl()
        {
            return GameObject.CreatePrimitive(PrimitiveType.Cube);
        }

        protected override void FromBmsNum(string num)
        {
            // since 00 is used for empty notes, 1 ~ Z is valid range
            x = charToCoord(num[0]) / 35.0f;
            y = charToCoord(num[1]) / 35.0f;
        }

        private int charToCoord(char a)
        {
            if (char.IsDigit(a))
            {
                return a - '1';
            }
            else if (char.IsLetter(a))
            {
                return char.ToLower(a) - 'a' + 9;
            }

            throw new ArgumentException("wrong data");
        }
    }

    class RearNote : Note
    {
        protected override GameObject CreateGameObjectImpl()
        {
            throw new NotImplementedException();
        }

        protected override void FromBmsNum(string num)
        {
            throw new NotImplementedException();
        }
    }

    class EdgeNote : Note
    {
        protected override GameObject CreateGameObjectImpl()
        {
            throw new NotImplementedException();
        }

        protected override void FromBmsNum(string num)
        {
            throw new NotImplementedException();
        }
    }

    enum NoteType
    {
        Front,
        Rear,
        Edge,
        Action
    }

    enum HandType
    {
        Left,
        Right,
        None
    }
}