/*
 * Copyright (C) 2017 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.systemui.statusbar.policy;

import android.content.Context;
import android.content.res.Configuration;
import android.os.Handler;
import android.util.ArrayMap;

import com.android.systemui.plugins.Plugin;
import com.android.systemui.plugins.PluginListener;
import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.tuner.TunerService.Tunable;
import com.android.systemui.util.leak.LeakDetector;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.function.Consumer;
import java.util.function.Supplier;

import javax.inject.Inject;
import javax.inject.Singleton;

/**
 */
@Singleton
public class ExtensionControllerImpl implements ExtensionController {

    public static final int SORT_ORDER_PLUGIN  = 0;
    public static final int SORT_ORDER_TUNER   = 1;
    public static final int SORT_ORDER_FEATURE = 2;
    public static final int SORT_ORDER_UI_MODE = 3;
    public static final int SORT_ORDER_DEFAULT = 4;

    private final Context mDefaultContext;
    private final LeakDetector mLeakDetector;
    private final PluginManager mPluginManager;
    private final TunerService mTunerService;
    private final ConfigurationController mConfigurationController;

    /**
     */
    @Inject
    public ExtensionControllerImpl(Context context,
            LeakDetector leakDetector,
            PluginManager pluginManager,
            TunerService tunerService,
            ConfigurationController configurationController) {
        mDefaultContext = context;
        mLeakDetector = leakDetector;
        mPluginManager = pluginManager;
        mTunerService = tunerService;
        mConfigurationController = configurationController;
    }

    @Override
    public <T> ExtensionBuilder<T> newExtension(Class<T> cls) {
        return new ExtensionBuilder<>();
    }

    private interface Producer<T> {
        T get();

        void destroy();
    }

    private class ExtensionBuilder<T> implements ExtensionController.ExtensionBuilder<T> {

        private ExtensionImpl<T> mExtension = new ExtensionImpl<>();

        @Override
        public ExtensionController.ExtensionBuilder<T> withTunerFactory(TunerFactory<T> factory) {
            mExtension.addTunerFactory(factory, factory.keys());
            return this;
        }

        @Override
        public <P extends T> ExtensionController.ExtensionBuilder<T> withPlugin(Class<P> cls) {
            return withPlugin(cls, PluginManager.Helper.getAction(cls));
        }

        @Override
        public <P extends T> ExtensionController.ExtensionBuilder<T> withPlugin(Class<P> cls,
                String action) {
            return withPlugin(cls, action, null);
        }

        @Override
        public <P> ExtensionController.ExtensionBuilder<T> withPlugin(Class<P> cls,
                String action, PluginConverter<T, P> converter) {
            mExtension.addPlugin(action, cls, converter);
            return this;
        }

        @Override
        public ExtensionController.ExtensionBuilder<T> withDefault(Supplier<T> def) {
            mExtension.addDefault(def);
            return this;
        }

        @Override
        public ExtensionController.ExtensionBuilder<T> withUiMode(int uiMode,
                Supplier<T> supplier) {
            mExtension.addUiMode(uiMode, supplier);
            return this;
        }

        @Override
        public ExtensionController.ExtensionBuilder<T> withFeature(String feature,
                Supplier<T> supplier) {
            mExtension.addFeature(feature, supplier);
            return this;
        }

        @Override
        public ExtensionController.ExtensionBuilder<T> withCallback(
                Consumer<T> callback) {
            mExtension.mCallbacks.add(callback);
            return this;
        }

        @Override
        public ExtensionController.Extension<T> build() {
            // Sort items in ascending order
            Collections.sort(mExtension.mProducers, Comparator.comparingInt(Item::sortOrder));
            mExtension.notifyChanged();
            return mExtension;
        }
    }

    private class ExtensionImpl<T> implements ExtensionController.Extension<T> {
        private final ArrayList<Item<T>> mProducers = new ArrayList<>();
        private final ArrayList<Consumer<T>> mCallbacks = new ArrayList<>();
        private T mItem;
        private Context mPluginContext;

        public void addCallback(Consumer<T> callback) {
            mCallbacks.add(callback);
        }

        @Override
        public T get() {
            return mItem;
        }

        @Override
        public Context getContext() {
            return mPluginContext != null ? mPluginContext : mDefaultContext;
        }

        @Override
        public void destroy() {
            for (int i = 0; i < mProducers.size(); i++) {
                mProducers.get(i).destroy();
            }
        }

        @Override
        public T reload() {
            notifyChanged();
            return get();
        }

        @Override
        public void clearItem(boolean isDestroyed) {
            if (isDestroyed && mItem != null) {
                mLeakDetector.trackGarbage(mItem);
            }
            mItem = null;
        }

        private void notifyChanged() {
            if (mItem != null) {
                mLeakDetector.trackGarbage(mItem);
            }
            mItem = null;
            for (int i = 0; i < mProducers.size(); i++) {
                final T item = mProducers.get(i).get();
                if (item != null) {
                    mItem = item;
                    break;
                }
            }
            for (int i = 0; i < mCallbacks.size(); i++) {
                mCallbacks.get(i).accept(mItem);
            }
        }

        public void addDefault(Supplier<T> def) {
            mProducers.add(new Default(def));
        }

        public <P> void addPlugin(String action, Class<P> cls, PluginConverter<T, P> converter) {
            mProducers.add(new PluginItem(action, cls, converter));
        }

        public void addTunerFactory(TunerFactory<T> factory, String[] keys) {
            mProducers.add(new TunerItem(factory, keys));
        }

        public void addUiMode(int uiMode, Supplier<T> mode) {
            mProducers.add(new UiModeItem(uiMode, mode));
        }

        public void addFeature(String feature, Supplier<T> mode) {
            mProducers.add(new FeatureItem<>(feature, mode));
        }

        private class PluginItem<P extends Plugin> implements Item<T>, PluginListener<P> {
            private final PluginConverter<T, P> mConverter;
            private T mItem;

            public PluginItem(String action, Class<P> cls, PluginConverter<T, P> converter) {
                mConverter = converter;
                mPluginManager.addPluginListener(action, this, cls);
            }

            @Override
            public void onPluginConnected(P plugin, Context pluginContext) {
                mPluginContext = pluginContext;
                if (mConverter != null) {
                    mItem = mConverter.getInterfaceFromPlugin(plugin);
                } else {
                    mItem = (T) plugin;
                }
                notifyChanged();
            }

            @Override
            public void onPluginDisconnected(P plugin) {
                mPluginContext = null;
                mItem = null;
                notifyChanged();
            }

            @Override
            public T get() {
                return mItem;
            }

            @Override
            public void destroy() {
                mPluginManager.removePluginListener(this);
            }

            @Override
            public int sortOrder() {
                return SORT_ORDER_PLUGIN;
            }
        }

        private class TunerItem<T> implements Item<T>, Tunable {
            private final TunerFactory<T> mFactory;
            private final ArrayMap<String, String> mSettings = new ArrayMap<>();
            private T mItem;

            public TunerItem(TunerFactory<T> factory, String... setting) {
                mFactory = factory;
                mTunerService.addTunable(this, setting);
            }

            @Override
            public T get() {
                return mItem;
            }

            @Override
            public void destroy() {
                mTunerService.removeTunable(this);
            }

            @Override
            public void onTuningChanged(String key, String newValue) {
                mSettings.put(key, newValue);
                mItem = mFactory.create(mSettings);
                notifyChanged();
            }

            @Override
            public int sortOrder() {
                return SORT_ORDER_TUNER;
            }
        }

        private class UiModeItem<T> implements Item<T>, ConfigurationListener {

            private final int mDesiredUiMode;
            private final Supplier<T> mSupplier;
            private int mUiMode;
            private Handler mHandler = new Handler();

            public UiModeItem(int uiMode, Supplier<T> supplier) {
                mDesiredUiMode = uiMode;
                mSupplier = supplier;
                mUiMode = mDefaultContext.getResources().getConfiguration().uiMode
                        & Configuration.UI_MODE_TYPE_MASK;
                mConfigurationController.addCallback(this);
            }

            @Override
            public void onConfigChanged(Configuration newConfig) {
                int newMode = newConfig.uiMode & Configuration.UI_MODE_TYPE_MASK;
                if (newMode != mUiMode) {
                    mUiMode = newMode;
                    // Post to make sure we don't have concurrent modifications.
                    mHandler.post(ExtensionImpl.this::notifyChanged);
                }
            }

            @Override
            public T get() {
                return (mUiMode == mDesiredUiMode) ? mSupplier.get() : null;
            }

            @Override
            public void destroy() {
                mConfigurationController.removeCallback(this);
            }

            @Override
            public int sortOrder() {
                return SORT_ORDER_UI_MODE;
            }
        }

        private class FeatureItem<T> implements Item<T> {
            private final String mFeature;
            private final Supplier<T> mSupplier;

            public FeatureItem(String feature, Supplier<T> supplier) {
                mSupplier = supplier;
                mFeature = feature;
            }

            @Override
            public T get() {
                return mDefaultContext.getPackageManager().hasSystemFeature(mFeature)
                        ? mSupplier.get() : null;
            }

            @Override
            public void destroy() {

            }

            @Override
            public int sortOrder() {
                return SORT_ORDER_FEATURE;
            }
        }

        private class Default<T> implements Item<T> {
            private final Supplier<T> mSupplier;

            public Default(Supplier<T> supplier) {
                mSupplier = supplier;
            }

            @Override
            public T get() {
                return mSupplier.get();
            }

            @Override
            public void destroy() {

            }

            @Override
            public int sortOrder() {
                return SORT_ORDER_DEFAULT;
            }
        }
    }

    private interface Item<T> extends Producer<T> {
        int sortOrder();
    }
}
