1/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.deskclock.timer;
18
19import android.content.Context;
20import android.content.SharedPreferences;
21import android.os.Parcel;
22import android.os.Parcelable;
23import android.util.Log;
24import android.view.View;
25
26import com.android.deskclock.R;
27import com.android.deskclock.Utils;
28
29import java.util.ArrayList;
30import java.util.Collections;
31import java.util.Comparator;
32import java.util.HashSet;
33import java.util.Iterator;
34import java.util.Set;
35
36public class TimerObj implements Parcelable {
37
38    private static final String TAG = "TimerObj";
39    // Max timer length is 9 hours + 99 minutes + 9 seconds
40    public static final long MAX_TIMER_LENGTH = (9 * 3600 + 99 * 60  + 99) * 1000;
41    public static final long MINUTE_IN_MILLIS = 60 * 1000;
42
43    public int mTimerId;             // Unique id
44    public long mStartTime;          // With mTimeLeft , used to calculate the correct time
45    public long mTimeLeft;           // in the timer.
46    public long mOriginalLength;     // length set at start of timer and by +1 min after times up
47    public long mSetupLength;        // length set at start of timer
48    public View mView;
49    public int mState;
50    public String mLabel;
51    public boolean mDeleteAfterUse;
52
53    public static final int STATE_RUNNING = 1;
54    public static final int STATE_STOPPED = 2;
55    public static final int STATE_TIMESUP = 3;
56    public static final int STATE_DONE = 4;
57    public static final int STATE_RESTART = 5;
58    public static final int STATE_DELETED = 6;
59
60    private static final String PREF_TIMER_ID = "timer_id_";
61    private static final String PREF_START_TIME  = "timer_start_time_";
62    private static final String PREF_TIME_LEFT = "timer_time_left_";
63    private static final String PREF_ORIGINAL_TIME = "timer_original_timet_";
64    private static final String PREF_SETUP_TIME = "timer_setup_timet_";
65    private static final String PREF_STATE = "timer_state_";
66    private static final String PREF_LABEL = "timer_label_";
67    private static final String PREF_DELETE_AFTER_USE = "delete_after_use_";
68
69    private static final String PREF_TIMERS_LIST = "timers_list";
70
71    public static final Parcelable.Creator<TimerObj> CREATOR = new Parcelable.Creator<TimerObj>() {
72        @Override
73        public TimerObj createFromParcel(Parcel p) {
74            return new TimerObj(p);
75        }
76
77        @Override
78        public TimerObj[] newArray(int size) {
79            return new TimerObj[size];
80        }
81    };
82
83    public void writeToSharedPref(SharedPreferences prefs) {
84        SharedPreferences.Editor editor = prefs.edit();
85        String key = PREF_TIMER_ID + Integer.toString(mTimerId);
86        String id = Integer.toString(mTimerId);
87        editor.putInt (key, mTimerId);
88        key = PREF_START_TIME + id;
89        editor.putLong (key, mStartTime);
90        key = PREF_TIME_LEFT + id;
91        editor.putLong (key, mTimeLeft);
92        key = PREF_ORIGINAL_TIME + id;
93        editor.putLong (key, mOriginalLength);
94        key = PREF_SETUP_TIME + id;
95        editor.putLong (key, mSetupLength);
96        key = PREF_STATE + id;
97        editor.putInt (key, mState);
98        Set <String> timersList = prefs.getStringSet(PREF_TIMERS_LIST, new HashSet<String>());
99        timersList.add(id);
100        editor.putStringSet(PREF_TIMERS_LIST, timersList);
101        key = PREF_LABEL + id;
102        editor.putString(key, mLabel);
103        key = PREF_DELETE_AFTER_USE + id;
104        editor.putBoolean(key, mDeleteAfterUse);
105        editor.apply();
106    }
107
108
109    public void readFromSharedPref(SharedPreferences prefs) {
110        String id = Integer.toString(mTimerId);
111        String key = PREF_START_TIME + id;
112        mStartTime = prefs.getLong(key, 0);
113        key = PREF_TIME_LEFT + id;
114        mTimeLeft = prefs.getLong(key, 0);
115        key = PREF_ORIGINAL_TIME + id;
116        mOriginalLength = prefs.getLong(key, 0);
117        key = PREF_SETUP_TIME + id;
118        mSetupLength = prefs.getLong(key, 0);
119        key = PREF_STATE + id;
120        mState = prefs.getInt(key, 0);
121        key = PREF_LABEL + id;
122        mLabel = prefs.getString(key, "");
123        key = PREF_DELETE_AFTER_USE + id;
124        mDeleteAfterUse = prefs.getBoolean(key, false);
125    }
126
127    public void deleteFromSharedPref(SharedPreferences prefs) {
128        SharedPreferences.Editor editor = prefs.edit();
129        String key = PREF_TIMER_ID + Integer.toString(mTimerId);
130        String id = Integer.toString(mTimerId);
131        editor.remove (key);
132        key = PREF_START_TIME + id;
133        editor.remove (key);
134        key = PREF_TIME_LEFT + id;
135        editor.remove (key);
136        key = PREF_ORIGINAL_TIME + id;
137        editor.remove (key);
138        key = PREF_SETUP_TIME + id;
139        editor.remove (key);
140        key = PREF_STATE + id;
141        editor.remove (key);
142        Set <String> timersList = prefs.getStringSet(PREF_TIMERS_LIST, new HashSet<String>());
143        timersList.remove(id);
144        editor.putStringSet(PREF_TIMERS_LIST, timersList);
145        key = PREF_LABEL + id;
146        editor.remove(key);
147        key = PREF_DELETE_AFTER_USE + id;
148        editor.remove(key);
149        editor.commit();
150        //dumpTimersFromSharedPrefs(prefs);
151    }
152
153
154    @Override
155    public int describeContents() {
156        return 0;
157    }
158
159    @Override
160    public void writeToParcel(Parcel dest, int flags) {
161        dest.writeInt(mTimerId);
162        dest.writeLong(mStartTime);
163        dest.writeLong(mTimeLeft);
164        dest.writeLong(mOriginalLength);
165        dest.writeLong(mSetupLength);
166        dest.writeInt(mState);
167        dest.writeString(mLabel);
168    }
169
170    public TimerObj(Parcel p) {
171        mTimerId = p.readInt();
172        mStartTime = p.readLong();
173        mTimeLeft = p.readLong();
174        mOriginalLength = p.readLong();
175        mSetupLength = p.readLong();
176        mState = p.readInt();
177        mLabel = p.readString();
178    }
179
180    public TimerObj() {
181        this(0);
182    }
183
184    public TimerObj(long timerLength) {
185      init(timerLength);
186    }
187
188    public TimerObj(long length, String label) {
189        this(length);
190        mLabel = label != null ? label : "";
191    }
192
193    private void init (long length) {
194        /* TODO: mTimerId must avoid StopwatchService.NOTIFICATION_ID,
195         * TimerReceiver.IN_USE_NOTIFICATION_ID, and alarm ID's (which seem to be 1, 2, ..)
196         */
197        mTimerId = (int) Utils.getTimeNow();
198        mStartTime = Utils.getTimeNow();
199        mTimeLeft = mOriginalLength = mSetupLength = length;
200        mLabel = "";
201    }
202
203    public long updateTimeLeft(boolean forceUpdate) {
204        if (isTicking() || forceUpdate) {
205            long millis = Utils.getTimeNow();
206            mTimeLeft = mOriginalLength - (millis - mStartTime);
207        }
208        return mTimeLeft;
209    }
210
211    public String getLabelOrDefault(Context context) {
212        return (mLabel == null || mLabel.length() == 0) ? context.getString(
213                R.string.timer_notification_label)
214                : mLabel;
215    }
216
217    public boolean isTicking() {
218        return mState == STATE_RUNNING || mState == STATE_TIMESUP;
219    }
220
221    public boolean isInUse() {
222        return mState == STATE_RUNNING || mState == STATE_STOPPED;
223    }
224
225    public void addTime(long time) {
226        mTimeLeft = mOriginalLength - (Utils.getTimeNow() - mStartTime);
227        if (mTimeLeft < MAX_TIMER_LENGTH - time) {
228                mOriginalLength += time;
229        }
230    }
231
232    public boolean getDeleteAfterUse() {
233        return mDeleteAfterUse;
234    }
235
236    public long getTimesupTime() {
237        return mStartTime + mOriginalLength;
238    }
239
240
241    public static void getTimersFromSharedPrefs(
242            SharedPreferences prefs, ArrayList<TimerObj> timers) {
243        Object[] timerStrings =
244                prefs.getStringSet(PREF_TIMERS_LIST, new HashSet<String>()).toArray();
245        if (timerStrings.length > 0) {
246            for (int i = 0; i < timerStrings.length; i++) {
247                TimerObj t = new TimerObj();
248                t.mTimerId = Integer.parseInt((String)timerStrings[i]);
249                t.readFromSharedPref(prefs);
250                timers.add(t);
251            }
252            Collections.sort(timers, new Comparator<TimerObj>() {
253                @Override
254                public int compare(TimerObj timerObj1, TimerObj timerObj2) {
255                   return timerObj2.mTimerId - timerObj1.mTimerId;
256                }
257            });
258        }
259    }
260
261    public static void getTimersFromSharedPrefs(
262            SharedPreferences prefs, ArrayList<TimerObj> timers, int match) {
263        Object[] timerStrings = prefs.getStringSet(PREF_TIMERS_LIST, new HashSet<String>())
264                .toArray();
265        if (timerStrings.length > 0) {
266            for (int i = 0; i < timerStrings.length; i++) {
267                TimerObj t = new TimerObj();
268                t.mTimerId = Integer.parseInt((String) timerStrings[i]);
269                t.readFromSharedPref(prefs);
270                if (t.mState == match) {
271                    timers.add(t);
272                }
273            }
274        }
275    }
276
277    public static void putTimersInSharedPrefs(
278            SharedPreferences prefs, ArrayList<TimerObj> timers) {
279        if (timers.size() > 0) {
280            for (int i = 0; i < timers.size(); i++) {
281                TimerObj t = timers.get(i);
282                timers.get(i).writeToSharedPref(prefs);
283            }
284        }
285    }
286
287    public static void dumpTimersFromSharedPrefs(
288            SharedPreferences prefs) {
289        Object[] timerStrings =
290                prefs.getStringSet(PREF_TIMERS_LIST, new HashSet<String>()).toArray();
291        Log.v(TAG,"--------------------- timers list in shared prefs");
292        if (timerStrings.length > 0) {
293            for (int i = 0; i < timerStrings.length; i++) {
294                int id = Integer.parseInt((String)timerStrings[i]);
295                Log.v(TAG,"---------------------timer  " + (i + 1) + ": id - " + id);
296            }
297        }
298    }
299
300    public static void resetTimersInSharedPrefs(SharedPreferences prefs) {
301        ArrayList<TimerObj> timers = new  ArrayList<TimerObj>();
302        getTimersFromSharedPrefs(prefs, timers);
303        Iterator<TimerObj> i = timers.iterator();
304        while(i.hasNext()) {
305            TimerObj t = i.next();
306            t.mState = TimerObj.STATE_RESTART;
307            t.mTimeLeft = t. mOriginalLength = t.mSetupLength;
308            t.writeToSharedPref(prefs);
309        }
310    }
311
312}
313