/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.calendar;

import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.database.Cursor;
import android.os.Debug;
import android.preference.PreferenceManager;
import android.provider.Calendar.Attendees;
import android.provider.Calendar.Instances;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.text.format.Time;
import android.util.Log;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.concurrent.atomic.AtomicInteger;

// TODO: should Event be Parcelable so it can be passed via Intents?
public class Event implements Comparable, Cloneable {

    private static final boolean PROFILE = false;

    private static final String[] PROJECTION = new String[] {
            Instances.TITLE,                 // 0
            Instances.EVENT_LOCATION,        // 1
            Instances.ALL_DAY,               // 2
            Instances.COLOR,                 // 3
            Instances.EVENT_TIMEZONE,        // 4
            Instances.EVENT_ID,              // 5
            Instances.BEGIN,                 // 6
            Instances.END,                   // 7
            Instances._ID,                   // 8
            Instances.START_DAY,             // 9
            Instances.END_DAY,               // 10
            Instances.START_MINUTE,          // 11
            Instances.END_MINUTE,            // 12
            Instances.HAS_ALARM,             // 13
            Instances.RRULE,                 // 14
            Instances.RDATE,                 // 15
            Instances.SELF_ATTENDEE_STATUS,  // 16
    };

    // The indices for the projection array above.
    private static final int PROJECTION_TITLE_INDEX = 0;
    private static final int PROJECTION_LOCATION_INDEX = 1;
    private static final int PROJECTION_ALL_DAY_INDEX = 2;
    private static final int PROJECTION_COLOR_INDEX = 3;
    private static final int PROJECTION_TIMEZONE_INDEX = 4;
    private static final int PROJECTION_EVENT_ID_INDEX = 5;
    private static final int PROJECTION_BEGIN_INDEX = 6;
    private static final int PROJECTION_END_INDEX = 7;
    private static final int PROJECTION_START_DAY_INDEX = 9;
    private static final int PROJECTION_END_DAY_INDEX = 10;
    private static final int PROJECTION_START_MINUTE_INDEX = 11;
    private static final int PROJECTION_END_MINUTE_INDEX = 12;
    private static final int PROJECTION_HAS_ALARM_INDEX = 13;
    private static final int PROJECTION_RRULE_INDEX = 14;
    private static final int PROJECTION_RDATE_INDEX = 15;
    private static final int PROJECTION_SELF_ATTENDEE_STATUS_INDEX = 16;

    public long id;
    public int color;
    public CharSequence title;
    public CharSequence location;
    public boolean allDay;

    public int startDay;       // start Julian day
    public int endDay;         // end Julian day
    public int startTime;      // Start and end time are in minutes since midnight
    public int endTime;

    public long startMillis;   // UTC milliseconds since the epoch
    public long endMillis;     // UTC milliseconds since the epoch
    private int mColumn;
    private int mMaxColumns;

    public boolean hasAlarm;
    public boolean isRepeating;
    
    public int selfAttendeeStatus;

    // The coordinates of the event rectangle drawn on the screen.
    public float left;
    public float right;
    public float top;
    public float bottom;

    // These 4 fields are used for navigating among events within the selected
    // hour in the Day and Week view.
    public Event nextRight;
    public Event nextLeft;
    public Event nextUp;
    public Event nextDown;

    private static final int MIDNIGHT_IN_MINUTES = 24 * 60;

    @Override
    public final Object clone() {
        Event e = new Event();

        e.title = title;
        e.color = color;
        e.location = location;
        e.allDay = allDay;
        e.startDay = startDay;
        e.endDay = endDay;
        e.startTime = startTime;
        e.endTime = endTime;
        e.startMillis = startMillis;
        e.endMillis = endMillis;
        e.hasAlarm = hasAlarm;
        e.isRepeating = isRepeating;
        e.selfAttendeeStatus = selfAttendeeStatus;

        return e;
    }

    public final void copyTo(Event dest) {
        dest.id = id;
        dest.title = title;
        dest.color = color;
        dest.location = location;
        dest.allDay = allDay;
        dest.startDay = startDay;
        dest.endDay = endDay;
        dest.startTime = startTime;
        dest.endTime = endTime;
        dest.startMillis = startMillis;
        dest.endMillis = endMillis;
        dest.hasAlarm = hasAlarm;
        dest.isRepeating = isRepeating;
        dest.selfAttendeeStatus = selfAttendeeStatus;
    }

    public static final Event newInstance() {
        Event e = new Event();

        e.id = 0;
        e.title = null;
        e.color = 0;
        e.location = null;
        e.allDay = false;
        e.startDay = 0;
        e.endDay = 0;
        e.startTime = 0;
        e.endTime = 0;
        e.startMillis = 0;
        e.endMillis = 0;
        e.hasAlarm = false;
        e.isRepeating = false;
        e.selfAttendeeStatus = Attendees.ATTENDEE_STATUS_NONE;

        return e;
    }

    /**
     * Compares this event to the given event.  This is just used for checking
     * if two events differ.  It's not used for sorting anymore.
     */
    public final int compareTo(Object obj) {
        Event e = (Event) obj;

        // The earlier start day and time comes first
        if (startDay < e.startDay) return -1;
        if (startDay > e.startDay) return 1;
        if (startTime < e.startTime) return -1;
        if (startTime > e.startTime) return 1;

        // The later end time comes first (in order to put long strips on
        // the left).
        if (endDay < e.endDay) return 1;
        if (endDay > e.endDay) return -1;
        if (endTime < e.endTime) return 1;
        if (endTime > e.endTime) return -1;

        // Sort all-day events before normal events.
        if (allDay && !e.allDay) return -1;
        if (!allDay && e.allDay) return 1;

        // If two events have the same time range, then sort them in
        // alphabetical order based on their titles.
        int cmp = compareStrings(title, e.title);
        if (cmp != 0) {
            return cmp;
        }

        // If the titles are the same then compare the other fields
        // so that we can use this function to check for differences
        // between events.
        cmp = compareStrings(location, e.location);
        if (cmp != 0) {
            return cmp;
        }
        return 0;
    }

    /**
     * Compare string a with string b, but if either string is null,
     * then treat it (the null) as if it were the empty string ("").
     *
     * @param a the first string
     * @param b the second string
     * @return the result of comparing a with b after replacing null
     *  strings with "".
     */
    private int compareStrings(CharSequence a, CharSequence b) {
        String aStr, bStr;
        if (a != null) {
            aStr = a.toString();
        } else {
            aStr = "";
        }
        if (b != null) {
            bStr = b.toString();
        } else {
            bStr = "";
        }
        return aStr.compareTo(bStr);
    }

    /**
     * Loads <i>days</i> days worth of instances starting at <i>start</i>.
     */
    public static void loadEvents(Context context, ArrayList<Event> events,
            long start, int days, int requestId, AtomicInteger sequenceNumber) {

        if (PROFILE) {
            Debug.startMethodTracing("loadEvents");
        }

        Cursor c = null;

        events.clear();
        try {
            Time local = new Time();
            int count;

            local.set(start);
            int startDay = Time.getJulianDay(start, local.gmtoff);
            int endDay = startDay + days;

            local.monthDay += days;
            long end = local.normalize(true /* ignore isDst */);

            // Widen the time range that we query by one day on each end
            // so that we can catch all-day events.  All-day events are
            // stored starting at midnight in UTC but should be included
            // in the list of events starting at midnight local time.
            // This may fetch more events than we actually want, so we
            // filter them out below.
            //
            // The sort order is: events with an earlier start time occur
            // first and if the start times are the same, then events with
            // a later end time occur first. The later end time is ordered
            // first so that long rectangles in the calendar views appear on
            // the left side.  If the start and end times of two events are
            // the same then we sort alphabetically on the title.  This isn't
            // required for correctness, it just adds a nice touch.

            String orderBy = Instances.SORT_CALENDAR_VIEW;

            // Respect the preference to show/hide declined events
            SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
            boolean hideDeclined = prefs.getBoolean(CalendarPreferenceActivity.KEY_HIDE_DECLINED,
                    false);

            String where = null;
            if (hideDeclined) {
                where = Instances.SELF_ATTENDEE_STATUS + "!=" + Attendees.ATTENDEE_STATUS_DECLINED;
            }

            c = Instances.query(context.getContentResolver(), PROJECTION,
                    start - DateUtils.DAY_IN_MILLIS, end + DateUtils.DAY_IN_MILLIS, where, orderBy);

            if (c == null) {
                Log.e("Cal", "loadEvents() returned null cursor!");
                return;
            }

            // Check if we should return early because there are more recent
            // load requests waiting.
            if (requestId != sequenceNumber.get()) {
                return;
            }

            count = c.getCount();

            if (count == 0) {
                return;
            }

            Resources res = context.getResources();
            while (c.moveToNext()) {
                Event e = new Event();

                e.id = c.getLong(PROJECTION_EVENT_ID_INDEX);
                e.title = c.getString(PROJECTION_TITLE_INDEX);
                e.location = c.getString(PROJECTION_LOCATION_INDEX);
                e.allDay = c.getInt(PROJECTION_ALL_DAY_INDEX) != 0;
                String timezone = c.getString(PROJECTION_TIMEZONE_INDEX);

                if (e.title == null || e.title.length() == 0) {
                    e.title = res.getString(R.string.no_title_label);
                }

                if (!c.isNull(PROJECTION_COLOR_INDEX)) {
                    // Read the color from the database
                    e.color = c.getInt(PROJECTION_COLOR_INDEX);
                } else {
                    e.color = res.getColor(R.color.event_center);
                }

                long eStart = c.getLong(PROJECTION_BEGIN_INDEX);
                long eEnd = c.getLong(PROJECTION_END_INDEX);

                e.startMillis = eStart;
                e.startTime = c.getInt(PROJECTION_START_MINUTE_INDEX);
                e.startDay = c.getInt(PROJECTION_START_DAY_INDEX);

                e.endMillis = eEnd;
                e.endTime = c.getInt(PROJECTION_END_MINUTE_INDEX);
                e.endDay = c.getInt(PROJECTION_END_DAY_INDEX);

                if (e.startDay > endDay || e.endDay < startDay) {
                    continue;
                }

                e.hasAlarm = c.getInt(PROJECTION_HAS_ALARM_INDEX) != 0;

                // Check if this is a repeating event
                String rrule = c.getString(PROJECTION_RRULE_INDEX);
                String rdate = c.getString(PROJECTION_RDATE_INDEX);
                if (!TextUtils.isEmpty(rrule) || !TextUtils.isEmpty(rdate)) {
                    e.isRepeating = true;
                } else {
                    e.isRepeating = false;
                }
                
                e.selfAttendeeStatus = c.getInt(PROJECTION_SELF_ATTENDEE_STATUS_INDEX);

                events.add(e);
            }

            computePositions(events);
        } finally {
            if (c != null) {
                c.close();
            }
            if (PROFILE) {
                Debug.stopMethodTracing();
            }
        }
    }

    /**
     * Computes a position for each event.  Each event is displayed
     * as a non-overlapping rectangle.  For normal events, these rectangles
     * are displayed in separate columns in the week view and day view.  For
     * all-day events, these rectangles are displayed in separate rows along
     * the top.  In both cases, each event is assigned two numbers: N, and
     * Max, that specify that this event is the Nth event of Max number of
     * events that are displayed in a group. The width and position of each
     * rectangle depend on the maximum number of rectangles that occur at
     * the same time.
     *
     * @param eventsList the list of events, sorted into increasing time order
     */
    static void computePositions(ArrayList<Event> eventsList) {
        if (eventsList == null)
            return;

        // Compute the column positions separately for the all-day events
        doComputePositions(eventsList, false);
        doComputePositions(eventsList, true);
    }

    private static void doComputePositions(ArrayList<Event> eventsList,
            boolean doAllDayEvents) {
        ArrayList<Event> activeList = new ArrayList<Event>();
        ArrayList<Event> groupList = new ArrayList<Event>();

        long colMask = 0;
        int maxCols = 0;
        for (Event event : eventsList) {
            // Process all-day events separately
            if (event.allDay != doAllDayEvents)
                continue;

            long start = event.getStartMillis();
            if (false && event.allDay) {
                Event e = event;
                Log.i("Cal", "event start,end day: " + e.startDay + "," + e.endDay
                        + " start,end time: " + e.startTime + "," + e.endTime
                        + " start,end millis: " + e.getStartMillis() + "," + e.getEndMillis()
                        + " "  + e.title);
            }

            // Remove the inactive events. An event on the active list
            // becomes inactive when its end time is less than or equal to
            // the current event's start time.
            Iterator<Event> iter = activeList.iterator();
            while (iter.hasNext()) {
                Event active = iter.next();
                if (active.getEndMillis() <= start) {
                    if (false && event.allDay) {
                        Event e = active;
                        Log.i("Cal", "  removing: start,end day: " + e.startDay + "," + e.endDay
                                + " start,end time: " + e.startTime + "," + e.endTime
                                + " start,end millis: " + e.getStartMillis() + "," + e.getEndMillis()
                                + " "  + e.title);
                    }
                    colMask &= ~(1L << active.getColumn());
                    iter.remove();
                }
            }

            // If the active list is empty, then reset the max columns, clear
            // the column bit mask, and empty the groupList.
            if (activeList.isEmpty()) {
                for (Event ev : groupList) {
                    ev.setMaxColumns(maxCols);
                }
                maxCols = 0;
                colMask = 0;
                groupList.clear();
            }

            // Find the first empty column.  Empty columns are represented by
            // zero bits in the column mask "colMask".
            int col = findFirstZeroBit(colMask);
            if (col == 64)
                col = 63;
            colMask |= (1L << col);
            event.setColumn(col);
            activeList.add(event);
            groupList.add(event);
            int len = activeList.size();
            if (maxCols < len)
                maxCols = len;
        }
        for (Event ev : groupList) {
            ev.setMaxColumns(maxCols);
        }
    }

    public static int findFirstZeroBit(long val) {
        for (int ii = 0; ii < 64; ++ii) {
            if ((val & (1L << ii)) == 0)
                return ii;
        }
        return 64;
    }

    /**
     * Returns a darker version of the given color.  It does this by dividing
     * each of the red, green, and blue components by 2.  The alpha value is
     * preserved.
     */
    private static final int getDarkerColor(int color) {
        int darker = (color >> 1) & 0x007f7f7f;
        int alpha = color & 0xff000000;
        return alpha | darker;
    }

    // For testing. This method can be removed at any time.
    private static ArrayList<Event> createTestEventList() {
        ArrayList<Event> evList = new ArrayList<Event>();
        createTestEvent(evList, 1, 5, 10);
        createTestEvent(evList, 2, 5, 10);
        createTestEvent(evList, 3, 15, 20);
        createTestEvent(evList, 4, 20, 25);
        createTestEvent(evList, 5, 30, 70);
        createTestEvent(evList, 6, 32, 40);
        createTestEvent(evList, 7, 32, 40);
        createTestEvent(evList, 8, 34, 38);
        createTestEvent(evList, 9, 34, 38);
        createTestEvent(evList, 10, 42, 50);
        createTestEvent(evList, 11, 45, 60);
        createTestEvent(evList, 12, 55, 90);
        createTestEvent(evList, 13, 65, 75);

        createTestEvent(evList, 21, 105, 130);
        createTestEvent(evList, 22, 110, 120);
        createTestEvent(evList, 23, 115, 130);
        createTestEvent(evList, 24, 125, 140);
        createTestEvent(evList, 25, 127, 135);

        createTestEvent(evList, 31, 150, 160);
        createTestEvent(evList, 32, 152, 162);
        createTestEvent(evList, 33, 153, 163);
        createTestEvent(evList, 34, 155, 170);
        createTestEvent(evList, 35, 158, 175);
        createTestEvent(evList, 36, 165, 180);

        return evList;
    }

    // For testing. This method can be removed at any time.
    private static Event createTestEvent(ArrayList<Event> evList, int id,
            int startMinute, int endMinute) {
        Event ev = new Event();
        ev.title = "ev" + id;
        ev.startDay = 1;
        ev.endDay = 1;
        ev.setStartMillis(startMinute);
        ev.setEndMillis(endMinute);
        evList.add(ev);
        return ev;
    }

    public final void dump() {
        Log.e("Cal", "+-----------------------------------------+");
        Log.e("Cal", "+        id = " + id);
        Log.e("Cal", "+     color = " + color);
        Log.e("Cal", "+     title = " + title);
        Log.e("Cal", "+  location = " + location);
        Log.e("Cal", "+    allDay = " + allDay);
        Log.e("Cal", "+  startDay = " + startDay);
        Log.e("Cal", "+    endDay = " + endDay);
        Log.e("Cal", "+ startTime = " + startTime);
        Log.e("Cal", "+   endTime = " + endTime);
    }

    public final boolean intersects(int julianDay, int startMinute,
            int endMinute) {
        if (endDay < julianDay) {
            return false;
        }

        if (startDay > julianDay) {
            return false;
        }

        if (endDay == julianDay) {
            if (endTime < startMinute) {
                return false;
            }
            // An event that ends at the start minute should not be considered
            // as intersecting the given time span, but don't exclude
            // zero-length (or very short) events.
            if (endTime == startMinute
                    && (startTime != endTime || startDay != endDay)) {
                return false;
            }
        }

        if (startDay == julianDay && startTime > endMinute) {
            return false;
        }

        return true;
    }

    /**
     * Returns the event title and location separated by a comma.  If the
     * location is already part of the title (at the end of the title), then
     * just the title is returned.
     *
     * @return the event title and location as a String
     */
    public String getTitleAndLocation() {
        String text = title.toString();

        // Append the location to the title, unless the title ends with the
        // location (for example, "meeting in building 42" ends with the
        // location).
        if (location != null) {
            String locationString = location.toString();
            if (!text.endsWith(locationString)) {
                text += ", " + locationString;
            }
        }
        return text;
    }

    public void setColumn(int column) {
        mColumn = column;
    }

    public int getColumn() {
        return mColumn;
    }

    public void setMaxColumns(int maxColumns) {
        mMaxColumns = maxColumns;
    }

    public int getMaxColumns() {
        return mMaxColumns;
    }

    public void setStartMillis(long startMillis) {
        this.startMillis = startMillis;
    }

    public long getStartMillis() {
        return startMillis;
    }

    public void setEndMillis(long endMillis) {
        this.endMillis = endMillis;
    }

    public long getEndMillis() {
        return endMillis;
    }
}
