/*
 * Copyright (C) 2010 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.cts.verifier;

import com.android.compatibility.common.util.ReportLog;

import android.app.AlertDialog;
import android.app.Dialog;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.os.Bundle;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageButton;
import android.widget.Toast;

/**
 * {@link Activity}s to handle clicks to the pass and fail buttons of the pass fail buttons layout.
 *
 * <ol>
 *     <li>Include the pass fail buttons layout in your layout:
 *         <pre><include layout="@layout/pass_fail_buttons" /></pre>
 *     </li>
 *     <li>Extend one of the activities and call setPassFailButtonClickListeners after
 *         setting your content view.</li>
 *     <li>Make sure to call setResult(RESULT_CANCEL) in your Activity initially.</li>
 *     <li>Optionally call setInfoTextResources to add an info button that will show a
 *         dialog with instructional text.</li>
 * </ol>
 */
public class PassFailButtons {

    private static final int INFO_DIALOG_ID = 1337;

    private static final String INFO_DIALOG_VIEW_ID = "infoDialogViewId";
    private static final String INFO_DIALOG_TITLE_ID = "infoDialogTitleId";
    private static final String INFO_DIALOG_MESSAGE_ID = "infoDialogMessageId";

    // Interface mostly for making documentation and refactoring easier...
    private interface PassFailActivity {

        /**
         * Hooks up the pass and fail buttons to click listeners that will record the test results.
         * <p>
         * Call from {@link Activity#onCreate} after {@link Activity #setContentView(int)}.
         */
        void setPassFailButtonClickListeners();

        /**
         * Adds an initial informational dialog that appears when entering the test activity for
         * the first time. Also enables the visibility of an "Info" button between the "Pass" and
         * "Fail" buttons that can be clicked to show the information dialog again.
         * <p>
         * Call from {@link Activity#onCreate} after {@link Activity #setContentView(int)}.
         *
         * @param titleId for the text shown in the dialog title area
         * @param messageId for the text shown in the dialog's body area
         */
        void setInfoResources(int titleId, int messageId, int viewId);

        View getPassButton();

        /**
         * Returns a unique identifier for the test.  Usually, this is just the class name.
         */
        String getTestId();

        /** @return null or details about the test run. */
        String getTestDetails();

        /**
         * Set the result of the test and finish the activity.
         *
         * @param passed Whether or not the test passed.
         */
        void setTestResultAndFinish(boolean passed);

        /** @return A {@link ReportLog} that is used to record test metric data. */
        ReportLog getReportLog();
    }

    public static class Activity extends android.app.Activity implements PassFailActivity {
        private WakeLock mWakeLock;
        private final ReportLog reportLog;

        public Activity() {
           this.reportLog = new CtsVerifierReportLog();
        }

        @Override
        protected void onResume() {
            super.onResume();
            if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH)) {
                mWakeLock = ((PowerManager) getSystemService(Context.POWER_SERVICE))
                        .newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "PassFailButtons");
                mWakeLock.acquire();
            }
        }

        @Override
        protected void onPause() {
            super.onPause();
            if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH)) {
                mWakeLock.release();
            }
        }

        @Override
        public void setPassFailButtonClickListeners() {
            setPassFailClickListeners(this);
        }

        @Override
        public void setInfoResources(int titleId, int messageId, int viewId) {
            setInfo(this, titleId, messageId, viewId);
        }

        @Override
        public View getPassButton() {
            return getPassButtonView(this);
        }

        @Override
        public Dialog onCreateDialog(int id, Bundle args) {
            return createDialog(this, id, args);
        }

        @Override
        public String getTestId() {
            return getClass().getName();
        }

        @Override
        public String getTestDetails() {
            return null;
        }

        @Override
        public void setTestResultAndFinish(boolean passed) {
            PassFailButtons.setTestResultAndFinishHelper(
                    this, getTestId(), getTestDetails(), passed, getReportLog());
        }

        @Override
        public ReportLog getReportLog() { return reportLog; }
    }

    public static class ListActivity extends android.app.ListActivity implements PassFailActivity {

        private final ReportLog reportLog;

        public ListActivity() {
            this.reportLog = new CtsVerifierReportLog();
        }

        @Override
        public void setPassFailButtonClickListeners() {
            setPassFailClickListeners(this);
        }

        @Override
        public void setInfoResources(int titleId, int messageId, int viewId) {
            setInfo(this, titleId, messageId, viewId);
        }

        @Override
        public View getPassButton() {
            return getPassButtonView(this);
        }

        @Override
        public Dialog onCreateDialog(int id, Bundle args) {
            return createDialog(this, id, args);
        }

        @Override
        public String getTestId() {
            return getClass().getName();
        }

        @Override
        public String getTestDetails() {
            return null;
        }

        @Override
        public void setTestResultAndFinish(boolean passed) {
            PassFailButtons.setTestResultAndFinishHelper(
                    this, getTestId(), getTestDetails(), passed, getReportLog());
        }

        @Override
        public ReportLog getReportLog() { return reportLog; }
    }

    public static class TestListActivity extends AbstractTestListActivity
            implements PassFailActivity {

        private final ReportLog reportLog;

        public TestListActivity() {
            this.reportLog = new CtsVerifierReportLog();
        }

        @Override
        public void setPassFailButtonClickListeners() {
            setPassFailClickListeners(this);
        }

        @Override
        public void setInfoResources(int titleId, int messageId, int viewId) {
            setInfo(this, titleId, messageId, viewId);
        }

        @Override
        public View getPassButton() {
            return getPassButtonView(this);
        }

        @Override
        public Dialog onCreateDialog(int id, Bundle args) {
            return createDialog(this, id, args);
        }

        @Override
        public String getTestId() {
            return getClass().getName();
        }

        @Override
        public String getTestDetails() {
            return null;
        }

        @Override
        public void setTestResultAndFinish(boolean passed) {
            PassFailButtons.setTestResultAndFinishHelper(
                    this, getTestId(), getTestDetails(), passed, getReportLog());
        }

        @Override
        public ReportLog getReportLog() { return reportLog; }
    }

    private static <T extends android.app.Activity & PassFailActivity>
            void setPassFailClickListeners(final T activity) {
        View.OnClickListener clickListener = new View.OnClickListener() {
            @Override
            public void onClick(View target) {
                setTestResultAndFinish(activity, activity.getTestId(), activity.getTestDetails(),
                        activity.getReportLog(), target);
            }
        };

        View passButton = activity.findViewById(R.id.pass_button);
        passButton.setOnClickListener(clickListener);
        passButton.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View view) {
                Toast.makeText(activity, R.string.pass_button_text, Toast.LENGTH_SHORT).show();
                return true;
            }
        });

        View failButton = activity.findViewById(R.id.fail_button);
        failButton.setOnClickListener(clickListener);
        failButton.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View view) {
                Toast.makeText(activity, R.string.fail_button_text, Toast.LENGTH_SHORT).show();
                return true;
            }
        });
    }

    private static void setInfo(final android.app.Activity activity, final int titleId,
            final int messageId, final int viewId) {
        // Show the middle "info" button and make it show the info dialog when clicked.
        View infoButton = activity.findViewById(R.id.info_button);
        infoButton.setVisibility(View.VISIBLE);
        infoButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                showInfoDialog(activity, titleId, messageId, viewId);
            }
        });
        infoButton.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View view) {
                Toast.makeText(activity, R.string.info_button_text, Toast.LENGTH_SHORT).show();
                return true;
            }
        });

        // Show the info dialog if the user has never seen it before.
        if (!hasSeenInfoDialog(activity)) {
            showInfoDialog(activity, titleId, messageId, viewId);
        }
    }

    private static boolean hasSeenInfoDialog(android.app.Activity activity) {
        ContentResolver resolver = activity.getContentResolver();
        Cursor cursor = null;
        try {
            cursor = resolver.query(
                    TestResultsProvider.getTestNameUri(activity.getClass().getName()),
                    new String[] {TestResultsProvider.COLUMN_TEST_INFO_SEEN}, null, null, null);
            return cursor.moveToFirst() && cursor.getInt(0) > 0;
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }
    }

    private static void showInfoDialog(final android.app.Activity activity, int titleId,
            int messageId, int viewId) {
        Bundle args = new Bundle();
        args.putInt(INFO_DIALOG_TITLE_ID, titleId);
        args.putInt(INFO_DIALOG_MESSAGE_ID, messageId);
        args.putInt(INFO_DIALOG_VIEW_ID, viewId);
        activity.showDialog(INFO_DIALOG_ID, args);
    }

    private static Dialog createDialog(final android.app.Activity activity, int id, Bundle args) {
        switch (id) {
            case INFO_DIALOG_ID:
                return createInfoDialog(activity, id, args);
            default:
                throw new IllegalArgumentException("Bad dialog id: " + id);
        }
    }

    private static Dialog createInfoDialog(final android.app.Activity activity, int id,
            Bundle args) {
        int viewId = args.getInt(INFO_DIALOG_VIEW_ID);
        int titleId = args.getInt(INFO_DIALOG_TITLE_ID);
        int messageId = args.getInt(INFO_DIALOG_MESSAGE_ID);

        AlertDialog.Builder builder = new AlertDialog.Builder(activity).setIcon(
                android.R.drawable.ic_dialog_info).setTitle(titleId);
        if (viewId > 0) {
            LayoutInflater inflater = (LayoutInflater) activity
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            builder.setView(inflater.inflate(viewId, null));
        } else {
            builder.setMessage(messageId);
        }
        builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                markSeenInfoDialog(activity);
            }
        }).setOnCancelListener(new OnCancelListener() {
            @Override
            public void onCancel(DialogInterface dialog) {
                markSeenInfoDialog(activity);
            }
        });
        return builder.create();
    }

    private static void markSeenInfoDialog(android.app.Activity activity) {
        ContentResolver resolver = activity.getContentResolver();
        ContentValues values = new ContentValues(2);
        values.put(TestResultsProvider.COLUMN_TEST_NAME, activity.getClass().getName());
        values.put(TestResultsProvider.COLUMN_TEST_INFO_SEEN, 1);
        int numUpdated = resolver.update(
                TestResultsProvider.getTestNameUri(activity.getClass().getName()),
                values, null, null);
        if (numUpdated == 0) {
            resolver.insert(TestResultsProvider.RESULTS_CONTENT_URI, values);
        }
    }

    /** Set the test result corresponding to the button clicked and finish the activity. */
    private static void setTestResultAndFinish(android.app.Activity activity, String testId,
            String testDetails, ReportLog reportLog, View target) {
        boolean passed;
        switch (target.getId()) {
            case R.id.pass_button:
                passed = true;
                break;
            case R.id.fail_button:
                passed = false;
                break;
            default:
                throw new IllegalArgumentException("Unknown id: " + target.getId());
        }
        setTestResultAndFinishHelper(activity, testId, testDetails, passed, reportLog);
    }

    /** Set the test result and finish the activity. */
    private static void setTestResultAndFinishHelper(android.app.Activity activity, String testId,
            String testDetails, boolean passed, ReportLog reportLog) {
        if (passed) {
            TestResult.setPassedResult(activity, testId, testDetails, reportLog);
        } else {
            TestResult.setFailedResult(activity, testId, testDetails, reportLog);
        }

        activity.finish();
    }

    private static ImageButton getPassButtonView(android.app.Activity activity) {
        return (ImageButton) activity.findViewById(R.id.pass_button);
    }

    public static class CtsVerifierReportLog extends ReportLog {

    }
}
