1/*
2 * Copyright (C) 2013 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.camera.data;
18
19import com.google.common.base.Preconditions;
20
21import java.util.Comparator;
22import java.util.Date;
23
24/**
25 * Sort filmstrip items by newest first, then by most recently modified
26 * then by title comparison.
27 */
28public class NewestFirstComparator implements Comparator<FilmstripItem> {
29    private final Date mNow;
30
31    private static final int MILLIS_IN_DAY = 24 * 60 * 60 * 1000;
32
33    /**
34     * Construct a comparator that sorts items by newest first. We ignore future
35     * creation dates using the supplied current date as a baseline.
36     *
37     * @param now present date to be used in comparisons to rule out dates in
38     *            the future.
39     */
40    public NewestFirstComparator(Date now) {
41        Preconditions.checkNotNull(now);
42        // Buffer by 24 hours to protect against false positives due to intraday
43        // time zone issues.
44        mNow = new Date(now.getTime() + MILLIS_IN_DAY);
45    }
46
47    @Override
48    public int compare(FilmstripItem d1, FilmstripItem d2) {
49        FilmstripItemData d1Data = d1.getData();
50        FilmstripItemData d2Data = d2.getData();
51
52        // If creation date is in future, fall back to modified, b/19565464.
53        Date d1PrimaryDate = isFuture(d1Data.getCreationDate()) ?
54                d1Data.getLastModifiedDate() : d1Data.getCreationDate();
55        Date d2PrimaryDate = isFuture(d2Data.getCreationDate()) ?
56                d2Data.getLastModifiedDate() : d2Data.getCreationDate();
57
58        int cmp = compareDate(d1PrimaryDate, d2PrimaryDate);
59        if (cmp == 0) {
60            cmp = compareDate(d1Data.getLastModifiedDate(),
61                  d2Data.getLastModifiedDate());
62        }
63        if (cmp == 0) {
64            cmp = d1Data.getTitle().compareTo(d2Data.getTitle());
65        }
66        return cmp;
67    }
68
69    /**
70     * Normal date comparison will sort these oldest first,
71     * so invert the order by multiplying by -1.
72     */
73    private int compareDate(Date v1, Date v2) {
74        return v1.compareTo(v2) * -1;
75    }
76
77    /**
78     * Is the Date in the future from a base date. If the date is in the future
79     * (larger) than the base date provided, return true.
80     *
81     * @param date The date to check whether it is in the future
82     * @param base The date to use as a baseline 'present'
83     * @return true if date is in the future from base
84     */
85    private boolean isFuture(Date date) {
86        return mNow.compareTo(date) < 0;
87    }
88}