/*
 * Copyright (C) 2015 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.settings.dashboard;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.os.Process;
import android.support.annotation.VisibleForTesting;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;

import com.android.settings.SettingsActivity;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.drawer.DashboardCategory;
import com.android.settingslib.drawer.Tile;
import com.android.settingslib.utils.ThreadUtils;

import java.lang.reflect.Field;
import java.util.List;

public class SummaryLoader {
    private static final boolean DEBUG = DashboardSummary.DEBUG;
    private static final String TAG = "SummaryLoader";

    public static final String SUMMARY_PROVIDER_FACTORY = "SUMMARY_PROVIDER_FACTORY";

    private final Activity mActivity;
    private final ArrayMap<SummaryProvider, ComponentName> mSummaryProviderMap = new ArrayMap<>();
    private final ArrayMap<String, CharSequence> mSummaryTextMap = new ArrayMap<>();
    private final DashboardFeatureProvider mDashboardFeatureProvider;
    private final String mCategoryKey;

    private final Worker mWorker;
    private final HandlerThread mWorkerThread;

    private SummaryConsumer mSummaryConsumer;
    private boolean mListening;
    private boolean mWorkerListening;
    private ArraySet<BroadcastReceiver> mReceivers = new ArraySet<>();

    public SummaryLoader(Activity activity, String categoryKey) {
        mDashboardFeatureProvider = FeatureFactory.getFactory(activity)
                .getDashboardFeatureProvider(activity);
        mCategoryKey = categoryKey;
        mWorkerThread = new HandlerThread("SummaryLoader", Process.THREAD_PRIORITY_BACKGROUND);
        mWorkerThread.start();
        mWorker = new Worker(mWorkerThread.getLooper());
        mActivity = activity;
    }

    public void release() {
        mWorkerThread.quitSafely();
        // Make sure we aren't listening.
        setListeningW(false);
    }

    public void setSummaryConsumer(SummaryConsumer summaryConsumer) {
        mSummaryConsumer = summaryConsumer;
    }

    public void setSummary(SummaryProvider provider, final CharSequence summary) {
        final ComponentName component = mSummaryProviderMap.get(provider);
        ThreadUtils.postOnMainThread(() -> {

            final Tile tile = getTileFromCategory(
                    mDashboardFeatureProvider.getTilesForCategory(mCategoryKey), component);

            if (tile == null) {
                if (DEBUG) {
                    Log.d(TAG, "Can't find tile for " + component);
                }
                return;
            }
            if (DEBUG) {
                Log.d(TAG, "setSummary " + tile.title + " - " + summary);
            }

            updateSummaryIfNeeded(tile, summary);
        });
    }

    @VisibleForTesting
    void updateSummaryIfNeeded(Tile tile, CharSequence summary) {
        if (TextUtils.equals(tile.summary, summary)) {
            if (DEBUG) {
                Log.d(TAG, "Summary doesn't change, skipping summary update for " + tile.title);
            }
            return;
        }
        mSummaryTextMap.put(mDashboardFeatureProvider.getDashboardKeyForTile(tile), summary);
        tile.summary = summary;
        if (mSummaryConsumer != null) {
            mSummaryConsumer.notifySummaryChanged(tile);
        } else {
            if (DEBUG) {
                Log.d(TAG, "SummaryConsumer is null, skipping summary update for "
                        + tile.title);
            }
        }
    }

    /**
     * Only call from the main thread.
     */
    public void setListening(boolean listening) {
        if (mListening == listening) {
            return;
        }
        mListening = listening;
        // Unregister listeners immediately.
        for (int i = 0; i < mReceivers.size(); i++) {
            mActivity.unregisterReceiver(mReceivers.valueAt(i));
        }
        mReceivers.clear();

        mWorker.removeMessages(Worker.MSG_SET_LISTENING);
        if (!listening) {
            // Stop listen
            mWorker.obtainMessage(Worker.MSG_SET_LISTENING, 0 /* listening */).sendToTarget();
        } else {
            // Start listen
            if (mSummaryProviderMap.isEmpty()) {
                // Category not initialized yet, init before starting to listen
                if (!mWorker.hasMessages(Worker.MSG_GET_CATEGORY_TILES_AND_SET_LISTENING)) {
                    mWorker.sendEmptyMessage(Worker.MSG_GET_CATEGORY_TILES_AND_SET_LISTENING);
                }
            } else {
                // Category already initialized, start listening immediately
                mWorker.obtainMessage(Worker.MSG_SET_LISTENING, 1 /* listening */).sendToTarget();
            }
        }
    }

    private SummaryProvider getSummaryProvider(Tile tile) {
        if (!mActivity.getPackageName().equals(tile.intent.getComponent().getPackageName())) {
            // Not within Settings, can't load Summary directly.
            // TODO: Load summary indirectly.
            return null;
        }
        Bundle metaData = getMetaData(tile);
        if (metaData == null) {
            if (DEBUG) Log.d(TAG, "No metadata specified for " + tile.intent.getComponent());
            return null;
        }
        String clsName = metaData.getString(SettingsActivity.META_DATA_KEY_FRAGMENT_CLASS);
        if (clsName == null) {
            if (DEBUG) Log.d(TAG, "No fragment specified for " + tile.intent.getComponent());
            return null;
        }
        try {
            Class<?> cls = Class.forName(clsName);
            Field field = cls.getField(SUMMARY_PROVIDER_FACTORY);
            SummaryProviderFactory factory = (SummaryProviderFactory) field.get(null);
            return factory.createSummaryProvider(mActivity, this);
        } catch (ClassNotFoundException e) {
            if (DEBUG) Log.d(TAG, "Couldn't find " + clsName, e);
        } catch (NoSuchFieldException e) {
            if (DEBUG) Log.d(TAG, "Couldn't find " + SUMMARY_PROVIDER_FACTORY, e);
        } catch (ClassCastException e) {
            if (DEBUG) Log.d(TAG, "Couldn't cast " + SUMMARY_PROVIDER_FACTORY, e);
        } catch (IllegalAccessException e) {
            if (DEBUG) Log.d(TAG, "Couldn't get " + SUMMARY_PROVIDER_FACTORY, e);
        }
        return null;
    }

    private Bundle getMetaData(Tile tile) {
        return tile.metaData;
    }

    /**
     * Registers a receiver and automatically unregisters it when the activity is stopping.
     * This ensures that the receivers are unregistered immediately, since most summary loader
     * operations are asynchronous.
     */
    public void registerReceiver(final BroadcastReceiver receiver, final IntentFilter filter) {
        mActivity.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                if (!mListening) {
                    return;
                }
                mReceivers.add(receiver);
                mActivity.registerReceiver(receiver, filter);
            }
        });
    }

    /**
     * Updates all tile's summary to latest cached version. This is necessary to handle the case
     * where category is updated after summary change.
     */
    public void updateSummaryToCache(DashboardCategory category) {
        if (category == null) {
            return;
        }
        for (Tile tile : category.getTiles()) {
            final String key = mDashboardFeatureProvider.getDashboardKeyForTile(tile);
            if (mSummaryTextMap.containsKey(key)) {
                tile.summary = mSummaryTextMap.get(key);
            }
        }
    }

    private synchronized void setListeningW(boolean listening) {
        if (mWorkerListening == listening) {
            return;
        }
        mWorkerListening = listening;
        if (DEBUG) {
            Log.d(TAG, "Listening " + listening);
        }
        for (SummaryProvider p : mSummaryProviderMap.keySet()) {
            try {
                p.setListening(listening);
            } catch (Exception e) {
                Log.d(TAG, "Problem in setListening", e);
            }
        }
    }

    private synchronized void makeProviderW(Tile tile) {
        SummaryProvider provider = getSummaryProvider(tile);
        if (provider != null) {
            if (DEBUG) Log.d(TAG, "Creating " + tile);
            mSummaryProviderMap.put(provider, tile.intent.getComponent());
        }
    }

    private Tile getTileFromCategory(DashboardCategory category, ComponentName component) {
        if (category == null || category.getTilesCount() == 0) {
            return null;
        }
        final List<Tile> tiles = category.getTiles();
        final int tileCount = tiles.size();
        for (int j = 0; j < tileCount; j++) {
            final Tile tile = tiles.get(j);
            if (component.equals(tile.intent.getComponent())) {
                return tile;
            }
        }
        return null;
    }


    public interface SummaryProvider {
        void setListening(boolean listening);
    }

    public interface SummaryConsumer {
        void notifySummaryChanged(Tile tile);
    }

    public interface SummaryProviderFactory {
        SummaryProvider createSummaryProvider(Activity activity, SummaryLoader summaryLoader);
    }

    private class Worker extends Handler {
        private static final int MSG_GET_CATEGORY_TILES_AND_SET_LISTENING = 1;
        private static final int MSG_GET_PROVIDER = 2;
        private static final int MSG_SET_LISTENING = 3;

        public Worker(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_GET_CATEGORY_TILES_AND_SET_LISTENING:
                    final DashboardCategory category =
                            mDashboardFeatureProvider.getTilesForCategory(mCategoryKey);
                    if (category == null || category.getTilesCount() == 0) {
                        return;
                    }
                    final List<Tile> tiles = category.getTiles();
                    for (Tile tile : tiles) {
                        makeProviderW(tile);
                    }
                    setListeningW(true);
                    break;
                case MSG_GET_PROVIDER:
                    Tile tile = (Tile) msg.obj;
                    makeProviderW(tile);
                    break;
                case MSG_SET_LISTENING:
                    boolean listening = msg.obj != null && msg.obj.equals(1);
                    setListeningW(listening);
                    break;
            }
        }
    }
}
