package com.sharefaith.thesharefaithapp.models;

import org.json.JSONObject;

import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;

/**
 * Created by Anthony on 11/4/16.
 * Model for Calendar Month
 */
public class SFMonthModel
{
    /** holds a date */
    private Date mDate;
    /** Index of month */
    private int mMonthIndex;
    /** Index of year */
    private int mYearIndex;
    /** reference to calendar */
    private Calendar mCalendar;
    /** number visible previous month days */
    public int mPreMonthDays;
    /** number visible next month days */
    private int mPostMonthDays;
    /** Array of SFDayModels */
    public SFDayModel[] mDayModels;
    /** Event data in string */
    private String mEventData;

    /** Hashmap of month events */
    private HashMap<String,String> monthEvents = new HashMap<>(  );

    /**
     * Constructor
     * @param calendar
     * @param eventData
     */
    public SFMonthModel( Calendar calendar, String eventData)
    {
        this.mEventData = eventData;
        this.mCalendar = calendar;
        this.mMonthIndex = this.mCalendar.get( Calendar.MONTH );
        this.mYearIndex = this.mCalendar.get( Calendar.YEAR );
        this.mDate = this.mCalendar.getTime();

        getMonthEvents();
        setMonthDays();
        populateMonth();
        this.mCalendar.setTime( this.mDate );
    }

    /**
     * set the days for the month
     */
    private void setMonthDays()
    {
        this.mCalendar.set( Calendar.DAY_OF_MONTH,1 );
        this.mPreMonthDays = this.mCalendar.get( Calendar.DAY_OF_WEEK ) -1;
        this.mCalendar.set( Calendar.DAY_OF_MONTH, this.mCalendar.getActualMaximum( Calendar.DAY_OF_MONTH ) );
        this.mPostMonthDays = ( 7 - this.mCalendar.get( Calendar.DAY_OF_WEEK ) );
    }

    /**
     * populate the month
     */
    private void populateMonth()
    {
        this.mDayModels = new SFDayModel[this.mPreMonthDays + this.mCalendar.getActualMaximum( Calendar.DAY_OF_MONTH ) + this.mPostMonthDays];
        populatePreDays();
        populateCurrentMonth();
        populatePostDays();
    }

    /**
     * populate month with the visible days of the previous month
     */
    private void populatePreDays()
    {
        this.mCalendar.add( Calendar.MONTH, -1 );
        int lastDayOfMonth = this.mCalendar.getActualMaximum( Calendar.DAY_OF_MONTH );
        this.mCalendar.set(Calendar.DAY_OF_MONTH, lastDayOfMonth - (this.mPreMonthDays -1) );
        for( int i = 0; i < this.mPreMonthDays; i++ )
        {
            this.mDayModels[i] = new SFDayModel( this.mCalendar.get( Calendar.DAY_OF_MONTH ), this.mCalendar.get( Calendar.DAY_OF_WEEK) -1, false,
                    this.mCalendar.get( Calendar.MONTH ), this.mCalendar.get( Calendar.YEAR ), null );
            this.mCalendar.add( Calendar.DAY_OF_MONTH, 1 );
        }
    }

    /**
     * populate the current month days
     */
    private void populateCurrentMonth()
    {
        this.mCalendar.set( Calendar.MONTH, this.mMonthIndex );
        this.mCalendar.set( Calendar.YEAR, this.mYearIndex );
        this.mCalendar.set(Calendar.DAY_OF_MONTH, 1 );
        int max = this.mCalendar.getActualMaximum( Calendar.DAY_OF_MONTH ) + this.mPreMonthDays;
        for( int i = this.mPreMonthDays; i < max; i++ )
        {
            this.mDayModels[i] = new SFDayModel( this.mCalendar.get( Calendar.DAY_OF_MONTH ), this.mCalendar.get( Calendar.DAY_OF_WEEK) -1, true,
            this.mCalendar.get( Calendar.MONTH ), this.mCalendar.get( Calendar.YEAR ), monthEvents.get( String.valueOf( mCalendar.get( Calendar.DAY_OF_MONTH ) ) ) );
            this.mCalendar.add( Calendar.DAY_OF_MONTH, 1 );
        }
    }

    /**
     * populate the next months visible days
     */
    private void populatePostDays()
    {
        this.mCalendar.set( Calendar.MONTH, (this.mMonthIndex ) +1 );
        this.mCalendar.set(Calendar.DAY_OF_MONTH, 1 );
        for( int i = (this.mDayModels.length - this.mPostMonthDays); i < this.mDayModels.length; i++ )
        {
            this.mDayModels[i] = new SFDayModel( this.mCalendar.get( Calendar.DAY_OF_MONTH ), this.mCalendar.get( Calendar.DAY_OF_WEEK) -1, false,
                    this.mCalendar.get( Calendar.MONTH ), this.mCalendar.get( Calendar.YEAR ), null );
            this.mCalendar.add( Calendar.DAY_OF_MONTH, 1 );
        }
    }

    /**
     * get the events for the month
     */
    private void getMonthEvents()
    {
        //Log.d( "mtag","hit get month events" );
        try
        {
            JSONObject events = new JSONObject( mEventData );
            JSONObject orderedItems;
            //if(events.get(orde))
            //Log.d( "mtag","get month events->ordereditems = " + events.get("ordereditems") );
            if( events.has("ordereditems"))
            {
                orderedItems = (JSONObject) events.get( "ordereditems" );
                //Log.d( "mtag", "events object" +Events.toString());
                Iterator iterator = orderedItems.keys();
                while (iterator.hasNext())
                {
                    String eventKey = (String) iterator.next();
                    int eventYear = Integer.valueOf( eventKey.substring( 0, 4 ) );
                    int eventMonth = Integer.valueOf( eventKey.substring( 5, 7 ) );
                    String eventDay = String.valueOf( Integer.valueOf( eventKey.substring( 8 ) ) );

                    if (((int) mCalendar.get( Calendar.MONTH ) + 1) == eventMonth && (int) mCalendar.get( Calendar.YEAR ) == eventYear)
                    {
                        monthEvents.put( eventDay, orderedItems.get( eventKey ).toString() );
                        //Log.d( "mtag","Event = key: " + eventDay + ", event data: " + monthEvents.get( eventDay ));
                    }

                    //Log.d( "mtag","Event month = " + eventMonth + ", " + eventYear);
                }
            }

        } catch (Exception e)
        {
            e.printStackTrace();
        }
    }
}
