/*
 * Copyright (C) 2016 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.printspooler.ui;

import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ListActivity;
import android.app.LoaderManager;
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.Loader;
import android.content.pm.ResolveInfo;
import android.database.DataSetObserver;
import android.net.Uri;
import android.os.Bundle;
import android.print.PrintManager;
import android.printservice.recommendation.RecommendationInfo;
import android.print.PrintServiceRecommendationsLoader;
import android.print.PrintServicesLoader;
import android.printservice.PrintServiceInfo;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Log;
import android.util.Pair;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Adapter;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.android.printspooler.R;

import java.text.Collator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/**
 * This is an activity for adding a printer or. It consists of a list fed from three adapters:
 * <ul>
 *     <li>{@link #mEnabledServicesAdapter} for all enabled services. If a service has an {@link
 *         PrintServiceInfo#getAddPrintersActivityName() add printer activity} this is started
 *         when the item is clicked.</li>
 *     <li>{@link #mDisabledServicesAdapter} for all disabled services. Once clicked the settings page
 *         for this service is opened.</li>
 *     <li>{@link #mRecommendedServicesAdapter} for a link to all services. If this item is clicked
 *         the market app is opened to show all print services.</li>
 * </ul>
 */
public class AddPrinterActivity extends ListActivity implements AdapterView.OnItemClickListener {
    private static final String LOG_TAG = "AddPrinterActivity";

    /** Ids for the loaders */
    private static final int LOADER_ID_ENABLED_SERVICES = 1;
    private static final int LOADER_ID_DISABLED_SERVICES = 2;
    private static final int LOADER_ID_RECOMMENDED_SERVICES = 3;
    private static final int LOADER_ID_ALL_SERVICES = 4;

    /**
     * The enabled services list. This is filled from the {@link #LOADER_ID_ENABLED_SERVICES}
     * loader in {@link PrintServiceInfoLoaderCallbacks#onLoadFinished}.
     */
    private EnabledServicesAdapter mEnabledServicesAdapter;

    /**
     * The disabled services list. This is filled from the {@link #LOADER_ID_DISABLED_SERVICES}
     * loader in {@link PrintServiceInfoLoaderCallbacks#onLoadFinished}.
     */
    private DisabledServicesAdapter mDisabledServicesAdapter;

    /**
     * The recommended services list. This is filled from the
     * {@link #LOADER_ID_RECOMMENDED_SERVICES} loader in
     * {@link PrintServicePrintServiceRecommendationLoaderCallbacks#onLoadFinished}.
     */
    private RecommendedServicesAdapter mRecommendedServicesAdapter;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.add_printer_activity);

        mEnabledServicesAdapter = new EnabledServicesAdapter();
        mDisabledServicesAdapter = new DisabledServicesAdapter();
        mRecommendedServicesAdapter = new RecommendedServicesAdapter();

        ArrayList<ActionAdapter> adapterList = new ArrayList<>(3);
        adapterList.add(mEnabledServicesAdapter);
        adapterList.add(mRecommendedServicesAdapter);
        adapterList.add(mDisabledServicesAdapter);

        setListAdapter(new CombinedAdapter(adapterList));

        getListView().setOnItemClickListener(this);

        PrintServiceInfoLoaderCallbacks printServiceLoaderCallbacks =
                new PrintServiceInfoLoaderCallbacks();

        getLoaderManager().initLoader(LOADER_ID_ENABLED_SERVICES, null, printServiceLoaderCallbacks);
        getLoaderManager().initLoader(LOADER_ID_DISABLED_SERVICES, null, printServiceLoaderCallbacks);
        getLoaderManager().initLoader(LOADER_ID_RECOMMENDED_SERVICES, null,
                new PrintServicePrintServiceRecommendationLoaderCallbacks());
        getLoaderManager().initLoader(LOADER_ID_ALL_SERVICES, null, printServiceLoaderCallbacks);
    }

    /**
     * Callbacks for the loaders operating on list of {@link PrintServiceInfo print service infos}.
     */
    private class PrintServiceInfoLoaderCallbacks implements
            LoaderManager.LoaderCallbacks<List<PrintServiceInfo>> {
        @Override
        public Loader<List<PrintServiceInfo>> onCreateLoader(int id, Bundle args) {
            switch (id) {
                case LOADER_ID_ENABLED_SERVICES:
                    return new PrintServicesLoader(
                            (PrintManager) getSystemService(Context.PRINT_SERVICE),
                            AddPrinterActivity.this, PrintManager.ENABLED_SERVICES);
                case LOADER_ID_DISABLED_SERVICES:
                    return new PrintServicesLoader(
                            (PrintManager) getSystemService(Context.PRINT_SERVICE),
                            AddPrinterActivity.this, PrintManager.DISABLED_SERVICES);
                case LOADER_ID_ALL_SERVICES:
                    return new PrintServicesLoader(
                            (PrintManager) getSystemService(Context.PRINT_SERVICE),
                            AddPrinterActivity.this, PrintManager.ALL_SERVICES);
                default:
                    // not reached
                    return null;
            }
        }


        @Override
        public void onLoadFinished(Loader<List<PrintServiceInfo>> loader,
                List<PrintServiceInfo> data) {
            switch (loader.getId()) {
                case LOADER_ID_ENABLED_SERVICES:
                    mEnabledServicesAdapter.updateData(data);
                    break;
                case LOADER_ID_DISABLED_SERVICES:
                    mDisabledServicesAdapter.updateData(data);
                    break;
                case LOADER_ID_ALL_SERVICES:
                    mRecommendedServicesAdapter.updateInstalledServices(data);
                default:
                    // not reached
            }
        }

        @Override
        public void onLoaderReset(Loader<List<PrintServiceInfo>> loader) {
            if (!isFinishing()) {
                switch (loader.getId()) {
                    case LOADER_ID_ENABLED_SERVICES:
                        mEnabledServicesAdapter.updateData(null);
                        break;
                    case LOADER_ID_DISABLED_SERVICES:
                        mDisabledServicesAdapter.updateData(null);
                        break;
                    case LOADER_ID_ALL_SERVICES:
                        mRecommendedServicesAdapter.updateInstalledServices(null);
                        break;
                    default:
                        // not reached
                }
            }
        }
    }

    /**
     * Callbacks for the loaders operating on list of {@link RecommendationInfo print service
     * recommendations}.
     */
    private class PrintServicePrintServiceRecommendationLoaderCallbacks implements
            LoaderManager.LoaderCallbacks<List<RecommendationInfo>> {
        @Override
        public Loader<List<RecommendationInfo>> onCreateLoader(int id, Bundle args) {
            return new PrintServiceRecommendationsLoader(
                    (PrintManager) getSystemService(Context.PRINT_SERVICE),
                    AddPrinterActivity.this);
        }


        @Override
        public void onLoadFinished(Loader<List<RecommendationInfo>> loader,
                List<RecommendationInfo> data) {
            mRecommendedServicesAdapter.updateRecommendations(data);
        }

        @Override
        public void onLoaderReset(Loader<List<RecommendationInfo>> loader) {
            if (!isFinishing()) {
                mRecommendedServicesAdapter.updateRecommendations(null);
            }
        }
    }

    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        ((ActionAdapter) getListAdapter()).performAction(position);
    }

    /**
     * Marks an adapter that can can perform an action for a position in it's list.
     */
    private abstract class ActionAdapter extends BaseAdapter {
        /**
         * Perform the action for a position in the list.
         *
         * @param position The position of the item
         */
        abstract void performAction(@IntRange(from = 0) int position);

        @Override
        public boolean areAllItemsEnabled() {
            return false;
        }
    }

    /**
     * An adapter presenting multiple sub adapters as a single combined adapter.
     */
    private class CombinedAdapter extends ActionAdapter {
        /** The adapters to combine */
        private final @NonNull ArrayList<ActionAdapter> mAdapters;

        /**
         * Create a combined adapter.
         *
         * @param adapters the list of adapters to combine
         */
        CombinedAdapter(@NonNull ArrayList<ActionAdapter> adapters) {
            mAdapters = adapters;

            final int numAdapters = mAdapters.size();
            for (int i = 0; i < numAdapters; i++) {
                mAdapters.get(i).registerDataSetObserver(new DataSetObserver() {
                    @Override
                    public void onChanged() {
                        notifyDataSetChanged();
                    }

                    @Override
                    public void onInvalidated() {
                        notifyDataSetChanged();
                    }
                });
            }
        }

        @Override
        public int getCount() {
            int totalCount = 0;

            final int numAdapters = mAdapters.size();
            for (int i = 0; i < numAdapters; i++) {
                totalCount += mAdapters.get(i).getCount();
            }

            return totalCount;
        }

        /**
         * Find the sub adapter and the position in the sub-adapter the position in the combined
         * adapter refers to.
         *
         * @param position The position in the combined adapter
         *
         * @return The pair of adapter and position in sub adapter
         */
        private @NonNull Pair<ActionAdapter, Integer> getSubAdapter(int position) {
            final int numAdapters = mAdapters.size();
            for (int i = 0; i < numAdapters; i++) {
                ActionAdapter adapter = mAdapters.get(i);

                if (position < adapter.getCount()) {
                    return new Pair<>(adapter, position);
                } else {
                    position -= adapter.getCount();
                }
            }

            throw new IllegalArgumentException("Invalid position");
        }

        @Override
        public int getItemViewType(int position) {
            int numLowerViewTypes = 0;

            final int numAdapters = mAdapters.size();
            for (int i = 0; i < numAdapters; i++) {
                Adapter adapter = mAdapters.get(i);

                if (position < adapter.getCount()) {
                    return numLowerViewTypes + adapter.getItemViewType(position);
                } else {
                    numLowerViewTypes += adapter.getViewTypeCount();
                    position -= adapter.getCount();
                }
            }

            throw new IllegalArgumentException("Invalid position");
        }

        @Override
        public int getViewTypeCount() {
            int totalViewCount = 0;

            final int numAdapters = mAdapters.size();
            for (int i = 0; i < numAdapters; i++) {
                totalViewCount += mAdapters.get(i).getViewTypeCount();
            }

            return totalViewCount;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            Pair<ActionAdapter, Integer> realPosition = getSubAdapter(position);

            return realPosition.first.getView(realPosition.second, convertView, parent);
        }

        @Override
        public Object getItem(int position) {
            Pair<ActionAdapter, Integer> realPosition = getSubAdapter(position);

            return realPosition.first.getItem(realPosition.second);
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public boolean isEnabled(int position) {
            Pair<ActionAdapter, Integer> realPosition = getSubAdapter(position);

            return realPosition.first.isEnabled(realPosition.second);
        }

        @Override
        public void performAction(@IntRange(from = 0) int position) {
            Pair<ActionAdapter, Integer> realPosition = getSubAdapter(position);

            realPosition.first.performAction(realPosition.second);
        }
    }
    
    /**
     * Superclass for all adapters that just display a list of {@link PrintServiceInfo}.
     */
    private abstract class PrintServiceInfoAdapter extends ActionAdapter {
        /**
         * Raw data of the list.
         *
         * @see #updateData(List)
         */
        private @NonNull List<PrintServiceInfo> mServices;

        /**
         * Create a new adapter.
         */
        PrintServiceInfoAdapter() {
            mServices = Collections.emptyList();
        }

        /**
         * Update the data.
         *
         * @param services The new raw data.
         */
        void updateData(@Nullable List<PrintServiceInfo> services) {
            if (services == null || services.isEmpty()) {
                mServices = Collections.emptyList();
            } else {
                mServices = services;
            }

            notifyDataSetChanged();
        }

        @Override
        public int getViewTypeCount() {
            return 2;
        }

        @Override
        public int getItemViewType(int position) {
            if (position == 0) {
                return 0;
            } else {
                return 1;
            }
        }

        @Override
        public int getCount() {
            if (mServices.isEmpty()) {
                return 0;
            } else {
                return mServices.size() + 1;
            }
        }

        @Override
        public Object getItem(int position) {
            if (position == 0) {
                return null;
            } else {
                return mServices.get(position - 1);
            }
        }

        @Override
        public boolean isEnabled(int position) {
            return position != 0;
        }

        @Override
        public long getItemId(int position) {
            return position;
        }
    }

    /**
     * Adapter for the enabled services.
     */
    private class EnabledServicesAdapter extends PrintServiceInfoAdapter {
        @Override
        public void performAction(@IntRange(from = 0) int position) {
            Intent intent = getAddPrinterIntent((PrintServiceInfo) getItem(position));
            if (intent != null) {
                try {
                    startActivity(intent);
                } catch (ActivityNotFoundException|SecurityException e) {
                    Log.e(LOG_TAG, "Cannot start add printers activity", e);
                }
            }
        }

        /**
         * Get the intent used to launch the add printers activity.
         *
         * @param service The service the printer should be added for
         *
         * @return The intent to launch the activity or null if the activity could not be launched.
         */
        private Intent getAddPrinterIntent(@NonNull PrintServiceInfo service) {
            String addPrinterActivityName = service.getAddPrintersActivityName();

            if (!TextUtils.isEmpty(addPrinterActivityName)) {
                Intent intent = new Intent(Intent.ACTION_MAIN);
                intent.setComponent(new ComponentName(service.getComponentName().getPackageName(),
                                addPrinterActivityName));

                List<ResolveInfo> resolvedActivities = getPackageManager().queryIntentActivities(
                        intent, 0);
                if (!resolvedActivities.isEmpty()) {
                    // The activity is a component name, therefore it is one or none.
                    if (resolvedActivities.get(0).activityInfo.exported) {
                        return intent;
                    }
                }
            }

            return null;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            if (position == 0) {
                if (convertView == null) {
                    convertView = getLayoutInflater().inflate(R.layout.add_printer_list_header,
                            parent, false);
                }

                ((TextView) convertView.findViewById(R.id.text))
                        .setText(R.string.enabled_services_title);

                return convertView;
            }

            if (convertView == null) {
                convertView = getLayoutInflater().inflate(R.layout.enabled_print_services_list_item,
                        parent, false);
            }

            PrintServiceInfo service = (PrintServiceInfo) getItem(position);

            TextView title = (TextView) convertView.findViewById(R.id.title);
            ImageView icon = (ImageView) convertView.findViewById(R.id.icon);
            TextView subtitle = (TextView) convertView.findViewById(R.id.subtitle);

            title.setText(service.getResolveInfo().loadLabel(getPackageManager()));
            icon.setImageDrawable(service.getResolveInfo().loadIcon(getPackageManager()));

            if (getAddPrinterIntent(service) == null) {
                subtitle.setText(getString(R.string.cannot_add_printer));
            } else {
                subtitle.setText(getString(R.string.select_to_add_printers));
            }

            return convertView;
        }
    }

    /**
     * Adapter for the disabled services.
     */
    private class DisabledServicesAdapter extends PrintServiceInfoAdapter {
        @Override
        public void performAction(@IntRange(from = 0) int position) {
            ((PrintManager) getSystemService(Context.PRINT_SERVICE)).setPrintServiceEnabled(
                    ((PrintServiceInfo) getItem(position)).getComponentName(), true);
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            if (position == 0) {
                if (convertView == null) {
                    convertView = getLayoutInflater().inflate(R.layout.add_printer_list_header,
                            parent, false);
                }

                ((TextView) convertView.findViewById(R.id.text))
                        .setText(R.string.disabled_services_title);

                return convertView;
            }

            if (convertView == null) {
                convertView = getLayoutInflater().inflate(
                        R.layout.disabled_print_services_list_item, parent, false);
            }

            PrintServiceInfo service = (PrintServiceInfo) getItem(position);

            TextView title = (TextView) convertView.findViewById(R.id.title);
            ImageView icon = (ImageView) convertView.findViewById(R.id.icon);

            title.setText(service.getResolveInfo().loadLabel(getPackageManager()));
            icon.setImageDrawable(service.getResolveInfo().loadIcon(getPackageManager()));

            return convertView;
        }
    }

    /**
     * Adapter for the recommended services.
     */
    private class RecommendedServicesAdapter extends ActionAdapter {
        /** Package names of all installed print services */
        private @NonNull final ArraySet<String> mInstalledServices;

        /** All print service recommendations */
        private @Nullable List<RecommendationInfo> mRecommendations;

        /**
         * Sorted print service recommendations for services that are not installed
         *
         * @see #filterRecommendations
         */
        private @Nullable List<RecommendationInfo> mFilteredRecommendations;

        /**
         * Create a new adapter.
         */
        private RecommendedServicesAdapter() {
            mInstalledServices = new ArraySet<>();
        }

        @Override
        public int getCount() {
            if (mFilteredRecommendations == null) {
                return 2;
            } else {
                return mFilteredRecommendations.size() + 2;
            }
        }

        @Override
        public int getViewTypeCount() {
            return 3;
        }

        /**
         * @return The position the all services link is at.
         */
        private int getAllServicesPos() {
            return getCount() - 1;
        }

        @Override
        public int getItemViewType(int position) {
            if (position == 0) {
                return 0;
            } else if (getAllServicesPos() == position) {
                return 1;
            } else {
                return 2;
            }
        }

        @Override
        public Object getItem(int position) {
            if (position == 0 || position == getAllServicesPos()) {
                return null;
            } else {
                return mFilteredRecommendations.get(position - 1);
            }
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            if (position == 0) {
                if (convertView == null) {
                    convertView = getLayoutInflater().inflate(R.layout.add_printer_list_header,
                            parent, false);
                }

                ((TextView) convertView.findViewById(R.id.text))
                        .setText(R.string.recommended_services_title);

                return convertView;
            } else if (position == getAllServicesPos()) {
                if (convertView == null) {
                    convertView = getLayoutInflater().inflate(R.layout.all_print_services_list_item,
                            parent, false);
                }
            } else {
                RecommendationInfo recommendation = (RecommendationInfo) getItem(position);

                if (convertView == null) {
                    convertView = getLayoutInflater().inflate(
                            R.layout.print_service_recommendations_list_item, parent, false);
                }

                ((TextView) convertView.findViewById(R.id.title)).setText(recommendation.getName());

                ((TextView) convertView.findViewById(R.id.subtitle)).setText(getResources()
                        .getQuantityString(R.plurals.print_services_recommendation_subtitle,
                                recommendation.getNumDiscoveredPrinters(),
                                recommendation.getNumDiscoveredPrinters()));

                return convertView;
            }

            return convertView;
        }

        @Override
        public boolean isEnabled(int position) {
            return position != 0;
        }

        @Override
        public void performAction(@IntRange(from = 0) int position) {
            if (position == getAllServicesPos()) {
                String searchUri = Settings.Secure
                        .getString(getContentResolver(), Settings.Secure.PRINT_SERVICE_SEARCH_URI);

                if (searchUri != null) {
                    try {
                        startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(searchUri)));
                    } catch (ActivityNotFoundException e) {
                        Log.e(LOG_TAG, "Cannot start market", e);
                    }
                }
            } else {
                RecommendationInfo recommendation = (RecommendationInfo) getItem(position);

                try {
                    startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(getString(
                            R.string.uri_package_details, recommendation.getPackageName()))));
                } catch (ActivityNotFoundException e) {
                    Log.e(LOG_TAG, "Cannot start market", e);
                }
            }
        }

        /**
         * Filter recommended services.
         */
        private void filterRecommendations() {
            if (mRecommendations == null) {
                mFilteredRecommendations = null;
            } else {
                mFilteredRecommendations = new ArrayList<>();

                // Filter out recommendations for already installed services
                final int numRecommendations = mRecommendations.size();
                for (int i = 0; i < numRecommendations; i++) {
                    RecommendationInfo recommendation = mRecommendations.get(i);

                    if (!mInstalledServices.contains(recommendation.getPackageName())) {
                        mFilteredRecommendations.add(recommendation);
                    }
                }
            }

            notifyDataSetChanged();
        }

        /**
         * Update the installed print services.
         *
         * @param services The new set of services
         */
        public void updateInstalledServices(List<PrintServiceInfo> services) {
            mInstalledServices.clear();

            if (services != null) {
                final int numServices = services.size();
                for (int i = 0; i < numServices; i++) {
                    mInstalledServices.add(services.get(i).getComponentName().getPackageName());
                }
            }

            filterRecommendations();
        }

        /**
         * Update the recommended print services.
         *
         * @param recommendations The new set of recommendations
         */
        public void updateRecommendations(List<RecommendationInfo> recommendations) {
            if (recommendations != null) {
                final Collator collator = Collator.getInstance();

                // Sort recommendations (early conditions are more important)
                // - higher number of discovered printers first
                // - single vendor services first
                // - alphabetically
                Collections.sort(recommendations,
                        new Comparator<RecommendationInfo>() {
                            @Override public int compare(RecommendationInfo o1,
                                    RecommendationInfo o2) {
                                if (o1.getNumDiscoveredPrinters() !=
                                        o2.getNumDiscoveredPrinters()) {
                                    return o2.getNumDiscoveredPrinters() -
                                            o1.getNumDiscoveredPrinters();
                                } else if (o1.recommendsMultiVendorService()
                                        != o2.recommendsMultiVendorService()) {
                                    if (o1.recommendsMultiVendorService()) {
                                        return 1;
                                    } else {
                                        return -1;
                                    }
                                } else {
                                    return collator.compare(o1.getName().toString(),
                                            o2.getName().toString());
                                }
                            }
                        });
            }

            mRecommendations = recommendations;

            filterRecommendations();
        }
    }
}
