using UnityEngine;
using System.Collections;

public class MapData : MonoBehaviour {

    public Vector2 m_size = new Vector2( 50.0f, 50.0f );
    public int m_fieldCountX = 5;
    public int m_fieldCountY = 5;
    public GameObject m_fieldPrefab = null;
    [HideInInspector]
    public  bool[ ] m_enabledFields = null;
    [HideInInspector]
    public Field[ ] m_fields = null;
    [HideInInspector]
    public int m_houseX = 0;
    [HideInInspector]
    public int m_houseY = 0;
    [HideInInspector]
    public Vector2 m_bottomLeft = Vector2.zero;
    [HideInInspector]
    public Vector2 m_fieldSize = Vector2.zero;
    public static MapData ms_instance = null;
    public int m_maxField = 15;

    public static MapData get( ) {
        return ms_instance;
    }

    void Awake( ) {
        ms_instance = this;
    }

	void Start( ) {

        int fieldCount = m_fieldCountX * m_fieldCountY;
        m_enabledFields = new bool[ fieldCount ];
        m_fields = new Field[ fieldCount ];
        m_houseX = m_fieldCountX / 2;
        m_houseY = m_fieldCountY / 2;
        m_fieldSize = new Vector2( m_size.x / m_fieldCountX, m_size.y / m_fieldCountY  );
        m_bottomLeft.x = -m_size.x * 0.5f + m_fieldSize.x * 0.5f;
        m_bottomLeft.y = -m_size.y * 0.5f + m_fieldSize.y * 0.5f;

        for ( int y = 0; y < m_fieldCountY; y++ ) {

            for ( int x = 0; x < m_fieldCountX; x++ ) {

                if ( x != m_houseX || y != m_houseY ) {

                    int fieldIndex = y * m_fieldCountX + x;
                    GameObject go = Instantiate( m_fieldPrefab ) as GameObject;
                    m_fields[ fieldIndex ] = go.GetComponent<Field>( );

                    go.SetActive( false );
                    Vector3 position = getFieldPosition( x, y );
                    go.transform.position = position;
                }
            }
        }
	}

    public void reset( ) {

        for ( int y = 0; y < m_fieldCountY; y++ ) {

            for ( int x = 0; x < m_fieldCountX; x++ ) {

                if ( x != m_houseX || y != m_houseY ) {

                    int fieldIndex = y * m_fieldCountX + x;

                    Field f = getField( x, y );

                    if ( !f.isFullyDead( ) ) {
                        m_enabledFields[ fieldIndex ] = false;
                        f.reset( );
                        f.gameObject.SetActive( false );
                    }
                }
            }
        }
    }

	void Update( ) {

        for ( int y = 0; y < m_fieldCountY; y++ ) {

            for ( int x = 0; x < m_fieldCountX; x++ ) {

                if ( x != m_houseX || y != m_houseY ) {

                    int fieldIndex = y * m_fieldCountX + x;

                    if ( m_enabledFields[ fieldIndex ] ) {

                        if ( !m_fields[ fieldIndex ].gameObject.activeInHierarchy ) {
                            m_fields[ fieldIndex ].gameObject.SetActive( true );
                        }
                    }
                }
            }
        }
	}

    public Vector3 getFieldPosition( int x, int y ) {
        Vector3 result = new Vector3( m_bottomLeft.x + x * m_fieldSize.x, 0.0f, m_bottomLeft.y + y * m_fieldSize.y );
        return result;
    }

    public Vec2i getNearestField( Vector3 position ) {

        Vec2i result = new Vec2i( );

        position.x += m_size.x * 0.5f;
        position.z += m_size.y * 0.5f;
        position.x /= m_fieldSize.x;
        position.z /= m_fieldSize.y;

        result.x = ( int ) position.x;
        result.y = ( int ) position.z;

        return result;
    }

    public bool doesFieldExists( Vec2i field ) {

        bool result = false;

        if ( field.x >= 0 && field.x < m_fieldCountX
            && field.y >= 0 && field.y < m_fieldCountY
            && ( field.x != m_houseX || field.y != m_houseY ) ) {

            result = true;
        }

        return result;
    }

    public bool isFieldEnabled( int x, int y ) {
        bool result = m_enabledFields[ y * m_fieldCountX + x ];
        return result;
    }

    public Field getField( int x, int y ) {
        Field field = m_fields[ y * m_fieldCountX + x ];
        return field;
    }

    public int countEnabledFields( ) {

        int count = 0;

        for ( int y = 0; y < m_fieldCountY; y++ ) {

            for ( int x = 0; x < m_fieldCountX; x++ ) {

                if ( m_enabledFields[ y * m_fieldCountX + x ] ) {
                    count++;
                }
            }
        }

        return count;
    }

    public bool hasFreeField( ) {

        bool result = false;

        if ( countEnabledFields( ) < m_maxField ) {

            for ( int y = 0; y < m_fieldCountY; y++ ) {

                for ( int x = 0; x < m_fieldCountX; x++ ) {

                    if ( ( y != m_houseY || x != m_houseX )  && !m_enabledFields[ y * m_fieldCountX + x ] ) {
                        result = true;
                        x = m_fieldCountX;
                        y = m_fieldCountY;
                    }
                }
            }
        }

        return result;
    }

    public Vec2i getClosestHarvestableField( Vector3 position ) {

        Vec2i result = new Vec2i( );
        result.x = -1;
        result.y = -1;
        float minSqrDistance = 100.0f * 100.0f + 100.0f * 100.0f;

        for ( int y = 0; y < m_fieldCountY; y++ ) {

            for ( int x = 0; x < m_fieldCountX; x++ ) {

                if ( x != m_houseX || y != m_houseY ) {

                    Field f = getField( x, y );

                    if ( f.isReadyToHarvest( ) && !f.m_flaged ){

                        float sqrDistance = ( f.transform.position - position ).sqrMagnitude;

                        if ( sqrDistance < minSqrDistance ) {
                            result.x = x;
                            result.y = y;
                        }
                    }
                }
            }
        }

        return result;
    }

    public bool allFinished( ) {

        bool result =  true;

        if ( countEnabledFields( ) != m_maxField ) {

            result = false;

        } else {

            for ( int y = 0; result && y < m_fieldCountY; y++ ) {

                for ( int x = 0; result && x < m_fieldCountX; x++ ) {

                    if ( x != m_houseX || y != m_houseY ) {

                        Field f = getField( x, y );

                        if ( m_enabledFields[ y * m_fieldCountX + x ] ) {

                            if ( f.m_planted != CropType.none ) {

                                if ( !f.isFullyDead( ) ){

                                    if ( f.m_crops[ 0 ].gameObject.activeInHierarchy ) {
                                        result = false;
                                    }
                                }

                            } else {

                                result = false;
                            }
                        }
                    }
                }
            }
        }

        return result;
    }

    public int getActiveFieldCount( ) {

        int count = 0;

        for ( int y = 0; y < m_fieldCountY; y++ ) {

            for ( int x = 0; x < m_fieldCountX; x++ ) {

                if ( x != m_houseX || y != m_houseY ) {

                    Field f = getField( x, y );

                    if ( !f.isFullyDead( ) ){
                        count++;
                    }
                }
            }
        }

        return count;
    }
}
