/*
 * Copyright (C) 2013 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.camera.data;

import android.content.ContentResolver;
import android.content.Context;
import android.net.Uri;
import android.os.AsyncTask;
import android.view.View;

import com.android.camera.debug.Log;
import com.android.camera.filmstrip.ImageData;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

/**
 * A {@link LocalDataAdapter} that provides data in the camera folder.
 */
public class CameraDataAdapter implements LocalDataAdapter {
    private static final Log.Tag TAG = new Log.Tag("CameraDataAdapter");

    private static final int DEFAULT_DECODE_SIZE = 1600;

    private final Context mContext;

    private LocalDataList mImages;

    private Listener mListener;
    private LocalDataListener mLocalDataListener;
    private final int mPlaceHolderResourceId;

    private int mSuggestedWidth = DEFAULT_DECODE_SIZE;
    private int mSuggestedHeight = DEFAULT_DECODE_SIZE;
    private long mLastPhotoId = LocalMediaData.QUERY_ALL_MEDIA_ID;

    private LocalData mLocalDataToDelete;

    public CameraDataAdapter(Context context, int placeholderResource) {
        mContext = context;
        mImages = new LocalDataList();
        mPlaceHolderResourceId = placeholderResource;
    }

    @Override
    public void setLocalDataListener(LocalDataListener listener) {
        mLocalDataListener = listener;
    }

    @Override
    public void requestLoadNewPhotos() {
        LoadNewPhotosTask ltask = new LoadNewPhotosTask(mLastPhotoId);
        ltask.execute(mContext.getContentResolver());
    }

    @Override
    public void requestLoad() {
        QueryTask qtask = new QueryTask();
        qtask.execute(mContext);
    }

    @Override
    public AsyncTask updateMetadata(int dataId) {
        MetadataUpdateTask result = new MetadataUpdateTask();
        result.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, dataId);
        return result;
    }

    @Override
    public boolean isMetadataUpdated(int dataId) {
        if (dataId < 0 || dataId >= mImages.size()) {
            return true;
        }
        return mImages.get(dataId).isMetadataUpdated();
    }

    @Override
    public int getItemViewType(int dataId) {
        if (dataId > mImages.size() || dataId < 0) {
            return -1;
        }

        return mImages.get(dataId).getItemViewType().ordinal();
    }

    @Override
    public LocalData getLocalData(int dataID) {
        if (dataID < 0 || dataID >= mImages.size()) {
            return null;
        }

        return mImages.get(dataID);
    }

    @Override
    public int getTotalNumber() {
        return mImages.size();
    }

    @Override
    public ImageData getImageData(int id) {
        return getLocalData(id);
    }

    @Override
    public void suggestViewSizeBound(int w, int h) {
        mSuggestedWidth = w;
        mSuggestedHeight = h;
    }

    @Override
    public View getView(Context context, View recycled, int dataID) {
        if (dataID >= mImages.size() || dataID < 0) {
            return null;
        }

        return mImages.get(dataID).getView(
                context, recycled, mSuggestedWidth, mSuggestedHeight,
                mPlaceHolderResourceId, this, /* inProgress */ false);
    }

    @Override
    public void resizeView(Context context, int dataID, View view, int w, int h) {
        if (dataID >= mImages.size() || dataID < 0) {
            return;
        }
        mImages.get(dataID).loadFullImage(context, w, h, view, this);
    }

    @Override
    public void setListener(Listener listener) {
        mListener = listener;
        if (mImages.size() != 0) {
            mListener.onDataLoaded();
        }
    }

    @Override
    public boolean canSwipeInFullScreen(int dataID) {
        if (dataID < mImages.size() && dataID > 0) {
            return mImages.get(dataID).canSwipeInFullScreen();
        }
        return true;
    }

    @Override
    public void removeData(int dataID) {
        if (dataID >= mImages.size()) {
            return;
        }
        LocalData d = mImages.remove(dataID);
        // Delete previously removed data first.
        executeDeletion();
        mLocalDataToDelete = d;
        mListener.onDataRemoved(dataID, d);
    }

    @Override
    public boolean addData(LocalData newData) {
        final Uri uri = newData.getUri();
        int pos = findDataByContentUri(uri);
        if (pos != -1) {
            // a duplicate one, just do a substitute.
            Log.v(TAG, "found duplicate data");
            updateData(pos, newData);
            return false;
        } else {
            // a new data.
            insertData(newData);
            return true;
        }
    }

    @Override
    public int findDataByContentUri(Uri uri) {
        // LocalDataList will return in O(1) if the uri is not contained.
        // Otherwise the performance is O(n), but this is acceptable as we will
        // most often call this to find an element at the beginning of the list.
        return mImages.indexOf(uri);
    }

    @Override
    public boolean undoDataRemoval() {
        if (mLocalDataToDelete == null) return false;
        LocalData d = mLocalDataToDelete;
        mLocalDataToDelete = null;
        insertData(d);
        return true;
    }

    @Override
    public boolean executeDeletion() {
        if (mLocalDataToDelete == null) return false;

        DeletionTask task = new DeletionTask();
        task.execute(mLocalDataToDelete);
        mLocalDataToDelete = null;
        return true;
    }

    @Override
    public void flush() {
        replaceData(new LocalDataList());
    }

    @Override
    public void refresh(Uri uri) {
        final int pos = findDataByContentUri(uri);
        if (pos == -1) {
            return;
        }

        LocalData data = mImages.get(pos);
        LocalData refreshedData = data.refresh(mContext);

        // Refresh failed. Probably removed already.
        if (refreshedData == null && mListener != null) {
            mListener.onDataRemoved(pos, data);
            return;
        }
        updateData(pos, refreshedData);
    }

    @Override
    public void updateData(final int pos, LocalData data) {
        mImages.set(pos, data);
        if (mListener != null) {
            mListener.onDataUpdated(new UpdateReporter() {
                @Override
                public boolean isDataRemoved(int dataID) {
                    return false;
                }

                @Override
                public boolean isDataUpdated(int dataID) {
                    return (dataID == pos);
                }
            });
        }
    }

    private void insertData(LocalData data) {
        // Since this function is mostly for adding the newest data,
        // a simple linear search should yield the best performance over a
        // binary search.
        int pos = 0;
        Comparator<LocalData> comp = new LocalData.NewestFirstComparator();
        for (; pos < mImages.size()
                && comp.compare(data, mImages.get(pos)) > 0; pos++);
        mImages.add(pos, data);
        updateMetadata(pos);
        if (mListener != null) {
            mListener.onDataInserted(pos, data);
        }
    }

    /** Update all the data */
    private void replaceData(LocalDataList list) {
        if (list.size() == 0 && mImages.size() == 0) {
            return;
        }
        mImages = list;
        if (mListener != null) {
            mListener.onDataLoaded();
        }
    }

    @Override
    public List<AsyncTask> preloadItems(List<Integer> items) {
        List<AsyncTask> result = new ArrayList<AsyncTask>();
        for (Integer id : items) {
            if (!isMetadataUpdated(id)) {
                result.add(updateMetadata(id));
            }
        }
        return result;
    }

    @Override
    public void cancelItems(List<AsyncTask> loadTokens) {
        for (AsyncTask asyncTask : loadTokens) {
            if (asyncTask != null) {
                asyncTask.cancel(false);
            }
        }
    }

    @Override
    public List<Integer> getItemsInRange(int startPosition, int endPosition) {
        List<Integer> result = new ArrayList<Integer>();
        for (int i = Math.max(0, startPosition); i < endPosition; i++) {
            result.add(i);
        }
        return result;
    }

    @Override
    public int getCount() {
        return getTotalNumber();
    }

    private class LoadNewPhotosTask extends AsyncTask<ContentResolver, Void, List<LocalData>> {

        private long mMinPhotoId;

        public LoadNewPhotosTask(long lastPhotoId) {
            mMinPhotoId = lastPhotoId;
        }

        /**
         * Loads any new photos added to our storage directory since our last query.
         * @param contentResolvers {@link android.content.ContentResolver} to load data.
         * @return An {@link java.util.ArrayList} containing any new data.
         */
        @Override
        protected List<LocalData> doInBackground(ContentResolver... contentResolvers) {
            final ContentResolver cr = contentResolvers[0];
            return LocalMediaData.PhotoData.query(cr, LocalMediaData.PhotoData.CONTENT_URI,
                    mMinPhotoId);
        }

        @Override
        protected void onPostExecute(List<LocalData> newPhotoData) {
            if (!newPhotoData.isEmpty()) {
                LocalData newestPhoto = newPhotoData.get(0);
                // We may overlap with another load task or a query task, in which case we want
                // to be sure we never decrement the oldest seen id.
                mLastPhotoId = Math.max(mLastPhotoId, newestPhoto.getContentId());
            }
            // We may add data that is already present, but if we do, it will be deduped in addData.
            for (LocalData localData : newPhotoData) {
                addData(localData);
            }
        }
    }

    private class QueryTaskResult {
        public LocalDataList mLocalDataList;
        public long mLastPhotoId;

        public QueryTaskResult(LocalDataList localDataList, long lastPhotoId) {
            mLocalDataList = localDataList;
            mLastPhotoId = lastPhotoId;
        }
    }

    private class QueryTask extends AsyncTask<Context, Void, QueryTaskResult> {
        // The maximum number of data to load metadata for in a single task.
        private static final int MAX_METADATA = 5;

        /**
         * Loads all the photo and video data in the camera folder in background
         * and combine them into one single list.
         *
         * @param contexts {@link Context} to load all the data.
         * @return An {@link com.android.camera.data.CameraDataAdapter.QueryTaskResult} containing
         *  all loaded data and the highest photo id in the dataset.
         */
        @Override
        protected QueryTaskResult doInBackground(Context... contexts) {
            final Context context = contexts[0];
            final ContentResolver cr = context.getContentResolver();
            LocalDataList l = new LocalDataList();
            // Photos
            List<LocalData> photoData = LocalMediaData.PhotoData.query(cr,
                    LocalMediaData.PhotoData.CONTENT_URI, LocalMediaData.QUERY_ALL_MEDIA_ID);
            List<LocalData> videoData = LocalMediaData.VideoData.query(cr,
                    LocalMediaData.VideoData.CONTENT_URI, LocalMediaData.QUERY_ALL_MEDIA_ID);

            long lastPhotoId = LocalMediaData.QUERY_ALL_MEDIA_ID;
            if (!photoData.isEmpty()) {
                lastPhotoId = photoData.get(0).getContentId();
            }

            l.addAll(photoData);
            l.addAll(videoData);
            l.sort(new LocalData.NewestFirstComparator());

            // Load enough metadata so it's already loaded when we open the filmstrip.
            for (int i = 0; i < MAX_METADATA && i < l.size(); i++) {
                LocalData data = l.get(i);
                MetadataLoader.loadMetadata(context, data);
            }

            return new QueryTaskResult(l, lastPhotoId);
        }

        @Override
        protected void onPostExecute(QueryTaskResult result) {
            // Since we're wiping away all of our data, we should always replace any existing last
            // photo id with the new one we just obtained so it matches the data we're showing.
            mLastPhotoId = result.mLastPhotoId;
            replaceData(result.mLocalDataList);
        }
    }

    private class DeletionTask extends AsyncTask<LocalData, Void, Void> {
        @Override
        protected Void doInBackground(LocalData... data) {
            for (int i = 0; i < data.length; i++) {
                if (!data[i].isDataActionSupported(LocalData.DATA_ACTION_DELETE)) {
                    Log.v(TAG, "Deletion is not supported:" + data[i]);
                    continue;
                }
                data[i].delete(mContext);
            }
            return null;
        }
    }

    private class MetadataUpdateTask extends AsyncTask<Integer, Void, List<Integer> > {
        @Override
        protected List<Integer> doInBackground(Integer... dataId) {
            List<Integer> updatedList = new ArrayList<Integer>();
            for (Integer id : dataId) {
                if (id < 0 || id >= mImages.size()) {
                    continue;
                }
                final LocalData data = mImages.get(id);
                if (MetadataLoader.loadMetadata(mContext, data)) {
                    updatedList.add(id);
                }
            }
            return updatedList;
        }

        @Override
        protected void onPostExecute(List<Integer> updatedData) {
            if (mLocalDataListener == null) {
                return;
            }
            mLocalDataListener.onMetadataUpdated(updatedData);
        }
    }
}
