/*
 * Copyright (C) 2014 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.example.android.support.wearable.notifications;

import android.app.Activity;
import android.app.Notification;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v4.app.NotificationManagerCompat;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;

import java.util.Arrays;

/**
 * Main activity which posts a notification when resumed, and allows customization
 * of that notification via controls.
 */
public class MainActivity extends Activity implements Handler.Callback {
    private static final int MSG_POST_NOTIFICATIONS = 0;
    private static final long POST_NOTIFICATIONS_DELAY_MS = 200;

    private Handler mHandler;
    private Spinner mPresetSpinner;
    private EditText mTitleEditText;
    private EditText mTextEditText;
    private TextWatcher mTextChangedListener;
    private Spinner mPrioritySpinner;
    private Spinner mActionsSpinner;
    private CheckBox mIncludeLargeIconCheckbox;
    private CheckBox mLocalOnlyCheckbox;
    private CheckBox mIncludeContentIntentCheckbox;
    private CheckBox mVibrateCheckbox;
    private BackgroundPickers mBackgroundPickers;
    private int mPostedNotificationCount = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mHandler = new Handler(this);
        mTextChangedListener = new UpdateNotificationsOnTextChangeListener();

        initPresetSpinner();
        initTitleEditText();
        initTextEditText();
        initPrioritySpinner();
        initActionsSpinner();
        initIncludeLargeIconCheckbox();
        initLocalOnlyCheckbox();
        initIncludeContentIntentCheckbox();
        initVibrateCheckbox();
        initBackgroundPickers();

        NotificationPreset preset = NotificationPresets.PRESETS[
                mPresetSpinner.getSelectedItemPosition()];
        updateTextEditors(preset);
    }

    @Override
    protected void onResume() {
        super.onResume();
        updateNotifications(false /* cancelExisting */);
    }

    private void initPresetSpinner() {
        mPresetSpinner = (Spinner) findViewById(R.id.preset_spinner);
        mPresetSpinner.setAdapter(new NamedPresetSpinnerArrayAdapter(this,
                NotificationPresets.PRESETS));
        mPresetSpinner.post(new Runnable() {
            @Override
            public void run() {
                mPresetSpinner.setOnItemSelectedListener(new PresetSpinnerListener());
            }
        });
    }

    private void initTitleEditText() {
        mTitleEditText = (EditText) findViewById(R.id.title_editor);
    }

    private void initTextEditText() {
        mTextEditText = (EditText) findViewById(R.id.text_editor);
    }

    private void initPrioritySpinner() {
        mPrioritySpinner = (Spinner) findViewById(R.id.priority_spinner);
        mPrioritySpinner.setAdapter(new NamedPresetSpinnerArrayAdapter(this,
                PriorityPresets.PRESETS));
        mPrioritySpinner.setSelection(Arrays.asList(PriorityPresets.PRESETS)
                .indexOf(PriorityPresets.DEFAULT));
        mPrioritySpinner.post(new Runnable() {
            @Override
            public void run() {
                mPrioritySpinner.setOnItemSelectedListener(
                        new UpdateNotificationsOnItemSelectedListener(true /* cancelExisting */));
            }
        });
    }

    private void initActionsSpinner() {
        mActionsSpinner = (Spinner) findViewById(R.id.actions_spinner);
        mActionsSpinner.setAdapter(new NamedPresetSpinnerArrayAdapter(this,
                ActionsPresets.PRESETS));
        mActionsSpinner.post(new Runnable() {
            @Override
            public void run() {
                mActionsSpinner.setOnItemSelectedListener(
                        new UpdateNotificationsOnItemSelectedListener(false /* cancelExisting */));
            }
        });
    }

    private void initIncludeLargeIconCheckbox() {
        mIncludeLargeIconCheckbox = (CheckBox) findViewById(R.id.include_large_icon_checkbox);
        mIncludeLargeIconCheckbox.setOnCheckedChangeListener(
                new UpdateNotificationsOnCheckedChangeListener(false /* cancelExisting */));
    }

    private void initLocalOnlyCheckbox() {
        mLocalOnlyCheckbox = (CheckBox) findViewById(R.id.local_only_checkbox);
        mLocalOnlyCheckbox.setOnCheckedChangeListener(
                new UpdateNotificationsOnCheckedChangeListener(false /* cancelExisting */));
    }

    private void initIncludeContentIntentCheckbox() {
        mIncludeContentIntentCheckbox = (CheckBox) findViewById(
                R.id.include_content_intent_checkbox);
        mIncludeContentIntentCheckbox.setOnCheckedChangeListener(
                new UpdateNotificationsOnCheckedChangeListener(false /* cancelExisting */));
    }

    private void initVibrateCheckbox() {
        mVibrateCheckbox = (CheckBox) findViewById(R.id.vibrate_checkbox);
        mVibrateCheckbox.setOnCheckedChangeListener(
                new UpdateNotificationsOnCheckedChangeListener(false /* cancelExisting */));
    }

    private void initBackgroundPickers() {
        mBackgroundPickers = new BackgroundPickers(
                (ViewGroup) findViewById(R.id.background_pickers),
                new BackgroundPickerListener());
    }

    private void updateTextEditors(NotificationPreset preset) {
        mTitleEditText.setText(getString(preset.titleResId));
        mTextEditText.setText(getString(preset.textResId));

        View[] presetViews = {
                findViewById(R.id.title_label),
                findViewById(R.id.title_editor),
                findViewById(R.id.text_label),
                findViewById(R.id.text_editor)
        };

        if (preset == NotificationPresets.BASIC) {
            for (View v : presetViews) {
                v.setVisibility(View.VISIBLE);
            }
            mTitleEditText.addTextChangedListener(mTextChangedListener);
            mTextEditText.addTextChangedListener(mTextChangedListener);
        } else {
            for (View v : presetViews) {
                v.setVisibility(View.GONE);
            }
            mTitleEditText.removeTextChangedListener(mTextChangedListener);
            mTextEditText.removeTextChangedListener(mTextChangedListener);
        }
    }

    /**
     * Begin to re-post the sample notification(s).
     */
    private void updateNotifications(boolean cancelExisting) {
        // Disable messages to skip notification deleted messages during cancel.
        sendBroadcast(new Intent(NotificationIntentReceiver.ACTION_DISABLE_MESSAGES)
                .setClass(this, NotificationIntentReceiver.class));

        if (cancelExisting) {
            // Cancel all existing notifications to trigger fresh-posting behavior: For example,
            // switching from HIGH to LOW priority does not cause a reordering in Notification
            // Shade.
            NotificationManagerCompat.from(this).cancelAll();
            mPostedNotificationCount = 0;

            // Post the updated notifications on a delay to avoid a cancel+post race condition
            // with notification manager.
            mHandler.removeMessages(MSG_POST_NOTIFICATIONS);
            mHandler.sendEmptyMessageDelayed(MSG_POST_NOTIFICATIONS, POST_NOTIFICATIONS_DELAY_MS);
        } else {
            postNotifications();
        }
    }

    /**
     * Post the sample notification(s) using current options.
     */
    private void postNotifications() {
        sendBroadcast(new Intent(NotificationIntentReceiver.ACTION_ENABLE_MESSAGES)
                .setClass(this, NotificationIntentReceiver.class));

        Notification[] notifications = buildNotifications();

        // Post new notifications
        NotificationManagerCompat notificationManagerCompat = NotificationManagerCompat.from(this);
        for (int i = 0; i < notifications.length; i++) {
            notificationManagerCompat.notify(i, notifications[i]);
        }
        // Cancel any that are beyond the current count.
        for (int i = notifications.length; i < mPostedNotificationCount; i++) {
            notificationManagerCompat.cancel(i);
        }
        mPostedNotificationCount = notifications.length;
    }

    /**
     * Build the sample notifications
     */

    private Notification[] buildNotifications() {
        NotificationPreset preset = NotificationPresets.PRESETS[
                mPresetSpinner.getSelectedItemPosition()];
        ActionsPreset actionsPreset = ActionsPresets.PRESETS[
                mActionsSpinner.getSelectedItemPosition()];
        if (preset.actionsRequired() && actionsPreset == ActionsPresets.NO_ACTIONS_PRESET) {
            // If actions are required, but the no-actions preset was selected, change presets.
            actionsPreset = ActionsPresets.SINGLE_ACTION_PRESET;
            mActionsSpinner.setSelection(Arrays.asList(ActionsPresets.PRESETS).indexOf(
                    actionsPreset), true);
        }
        NotificationPreset.BuildOptions options = new NotificationPreset.BuildOptions(
                mTitleEditText.getText(),
                mTextEditText.getText(),
                PriorityPresets.PRESETS[mPrioritySpinner.getSelectedItemPosition()],
                actionsPreset,
                mIncludeLargeIconCheckbox.isChecked(),
                mLocalOnlyCheckbox.isChecked(),
                mIncludeContentIntentCheckbox.isChecked(),
                mVibrateCheckbox.isChecked(),
                mBackgroundPickers.getRes());
        return preset.buildNotifications(this, options);
    }

    @Override
    public boolean handleMessage(Message message) {
        switch (message.what) {
            case MSG_POST_NOTIFICATIONS:
                postNotifications();
                return true;
        }
        return false;
    }

    private class PresetSpinnerListener implements AdapterView.OnItemSelectedListener {
        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
            NotificationPreset preset = NotificationPresets.PRESETS[position];
            mBackgroundPickers.generatePickers(preset.countBackgroundPickersRequired());
            updateTextEditors(preset);
            updateNotifications(false /* cancelExisting */);
        }

        @Override
        public void onNothingSelected(AdapterView<?> adapterView) {}
    }

    private class UpdateNotificationsOnTextChangeListener implements TextWatcher {
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {}

        public void onTextChanged(CharSequence s, int start, int before, int count) {}

        @Override
        public void afterTextChanged(Editable s) {
            updateNotifications(false /* cancelExisting */);
        }
    }

    private class UpdateNotificationsOnItemSelectedListener
            implements AdapterView.OnItemSelectedListener {
        private final boolean mCancelExisting;

        public UpdateNotificationsOnItemSelectedListener(boolean cancelExisting) {
            mCancelExisting = cancelExisting;
        }
        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
            updateNotifications(mCancelExisting);
        }

        @Override
        public void onNothingSelected(AdapterView<?> adapterView) {
        }
    }

    private class UpdateNotificationsOnCheckedChangeListener
            implements CompoundButton.OnCheckedChangeListener {
        private final boolean mCancelExisting;

        public UpdateNotificationsOnCheckedChangeListener(boolean cancelExisting) {
            mCancelExisting = cancelExisting;
        }

        @Override
        public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
            updateNotifications(mCancelExisting);
        }
    }

    private class BackgroundPickerListener
            implements BackgroundPickers.OnBackgroundPickersChangedListener {
        @Override
        public void onBackgroundPickersChanged(BackgroundPickers pickers) {
            updateNotifications(false /* cancelExisting */);
        }
    }

    private class NamedPresetSpinnerArrayAdapter extends ArrayAdapter<NamedPreset> {
        public NamedPresetSpinnerArrayAdapter(Context context, NamedPreset[] presets) {
            super(context, R.layout.simple_spinner_item, presets);
        }

        @Override
        public View getDropDownView(int position, View convertView, ViewGroup parent) {
            TextView view = (TextView) super.getDropDownView(position, convertView, parent);
            view.setText(getString(getItem(position).nameResId));
            return view;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            TextView view = (TextView) getLayoutInflater().inflate(
                    android.R.layout.simple_spinner_item, parent, false);
            view.setText(getString(getItem(position).nameResId));
            return view;
        }
    }
}
