package jp.sourceforge.tamanegisoul.sa.action;

import java.util.Date;

import jp.sourceforge.tamanegisoul.sa.R;
import jp.sourceforge.tamanegisoul.sa.util.AppAccountManager;
import jp.sourceforge.tamanegisoul.sa.util.AppAlarmListener;
import jp.sourceforge.tamanegisoul.sa.util.AppAlarmManager;
import jp.sourceforge.tamanegisoul.sa.util.DBHelper;
import jp.sourceforge.tamanegisoul.sa.util.FormatUtils;
import jp.sourceforge.tamanegisoul.sa.util.LogUtil;
import jp.sourceforge.tamanegisoul.sa.util.PreferenceUtils;
import android.accounts.Account;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Service;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.os.Bundle;
import android.os.IBinder;
import android.preference.PreferenceManager;
import android.view.View;
import android.widget.Button;
import android.widget.CursorAdapter;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
import android.widget.TextView;

/**
 * メインのActivity
 */
public class DashboardActivity extends Activity implements OnSharedPreferenceChangeListener {

    /** スケジュール一覧のアダプタ */
    private CursorAdapter mScheduleListAdapter;
    /** 現在スケジュール表示中のアカウント。選択アカウント変更を検知するために… */
    private Account mCurrentAccount;

    @Override
    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
        LogUtil.d("DashboardActivity.onSharedPreferenceChanged(key->%s)", key);
        if (key.equals(PreferenceUtils.KEY_ACCOUNT)) {
            validateView();
        }
    }

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

        // このActivityがメインなのでサービスを起動
        startService(new Intent(getApplicationContext(), CalendarObserverService.class));
        bindService(new Intent(getApplicationContext(), CalendarObserverService.class), new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                LogUtil.d("DashboardActivity.ServiceConnection.onServiceConnected()");
                // カレンダーの更新リスナー
                ((CalendarObserverService.LocalBinder) service).getService().addOnCalendarChangeListener(new CalendarObserverService.OnCalendarChangeListener() {
                    @Override
                    public void onChange() {
                        LogUtil.d("DashboardActivity.CalendarObserverService.OnCalendarChangeListener.onChange()");
                        validateView();
                    }
                });
            }

            @Override
            public void onServiceDisconnected(ComponentName name) {
            }
        }, Service.BIND_AUTO_CREATE);

        // アラームの更新リスナー
        AppAlarmManager.getInstance(this).registerAppAlarmListener(new AppAlarmListener() {
            @Override
            public void alarmSet(Date date) {
                LogUtil.d("DashboardActivity.AppAlarmListener.onChange(%s)", date);
                validateView();
            }
        });

        // 設定の更新リスナー
        // 匿名クラスにすると呼ばれないので注意
        PreferenceManager.getDefaultSharedPreferences(getApplicationContext()).registerOnSharedPreferenceChangeListener(this);

        // 強制同期ボタン
        ((Button) findViewById(R.id.sync_button)).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Account account = AppAccountManager.getInstance(DashboardActivity.this).getAccount();
                if (account != null)
                    ContentResolver.requestSync(account, "com.android.calendar", new Bundle());
            }
        });
        // カレンダー表示ボタン
        ((Button) findViewById(R.id.calendar_button)).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://www.google.com/calendar")));
            }
        });
        // スヌーズ解除ボタン
        ((Button) findViewById(R.id.cancel_snooze_button)).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ((Button) findViewById(R.id.cancel_snooze_button)).setVisibility(View.GONE);
                // 次のアラームを設定
                AppAlarmManager.getInstance(DashboardActivity.this).cancelSnooze();
                AppAlarmManager.getInstance(DashboardActivity.this).refreshAlarm();
            }
        });
        // 予定一覧
        ((ListView) findViewById(R.id.schedule_list)).setEmptyView(findViewById(R.id.schedule_list_is_empty));
        // 設定ボタン
        ((Button) findViewById(R.id.preference_button)).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startActivity(new Intent(DashboardActivity.this, AppPreferenceActivity.class));
            }
        });
        // 祝日一覧ボタン
        ((Button) findViewById(R.id.holiday_list_button)).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startActivity(new Intent(DashboardActivity.this, HolidayListActivity.class));
            }
        });
        // ヘルプボタン
        ((Button) findViewById(R.id.help_button)).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                createHelpDialog().show();
            }
        });
    }

    @Override
    protected void onResume() {
        super.onResume();

        // 未設定なら設定画面を強制表示
        if (PreferenceUtils.getString(this, PreferenceUtils.KEY_WEEKDAY_TIME) == null || PreferenceUtils.getString(this, PreferenceUtils.KEY_HOLIDAY_TIME) == null) {
            // アラーム時刻が未設定
            showPreferenceNotSetDialog("アラーム時刻を設定してください");
        } else if (PreferenceUtils.getRingtone(this) == null && PreferenceUtils.getVibratorPattern(this) == null) {
            // 音、バイブレーターが未設定
            showPreferenceNotSetDialog("音またはバイブレーターを設定してください");
        }

        validateView();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mScheduleListAdapter != null)
            mScheduleListAdapter.getCursor().close();
        // 設定の更新リスナー
        PreferenceManager.getDefaultSharedPreferences(getApplicationContext()).unregisterOnSharedPreferenceChangeListener(this);
    }

    private void validateView() {
        // アカウント未設定なら同期ボタンを無効化
        ((Button) findViewById(R.id.sync_button)).setEnabled(PreferenceUtils.getString(this, PreferenceUtils.KEY_ACCOUNT) != null);
        // 次回アラーム表示更新
        ((TextView) findViewById(R.id.next_alarm_text)).setText(FormatUtils.formatDateTimeDisplay(AppAlarmManager.getInstance(this).getNextAlarmTime()));
        // 今日は何の日表示
        ((TextView) findViewById(R.id.day_notation)).setText(getTodayDescription());
        // スヌーズ中なら解除ボタン表示
        int visibility = PreferenceUtils.isProgressSnooze(this) ? View.VISIBLE : View.GONE;
        ((Button) findViewById(R.id.cancel_snooze_button)).setVisibility(visibility);
        // スケジュール一覧を更新
        refreshScheduleListAdapter();
        if (mScheduleListAdapter != null)
            mScheduleListAdapter.getCursor().requery();
        // 最新同期時刻
        ((TextView) findViewById(R.id.schedule_sync_time)).setText(FormatUtils.formatDateTimeDisplay(PreferenceUtils.getDateTime(this, PreferenceUtils.KEY_LATEST_SYNC_TIME)));
    }

    /**
     * @return 今日の日付を表わす文字列（祝日ならその名称）
     */
    private String getTodayDescription() {
        Date today = new Date();
        String description = "";
        SQLiteDatabase db = null;
        try {
            db = new DBHelper(this).getReadableDatabase();
            Cursor c = db.query(DBHelper.T_HOLIDAY, null, DBHelper.C_HOLIDAY_DATE + "=?", new String[] { FormatUtils.formatDate(today) }, null, null, null);
            if (c.moveToFirst())
                description = c.getString(c.getColumnIndex(DBHelper.C_HOLIDAY_NAME));
        } finally {
            if (db != null)
                db.close();
        }
        return String.format("今日は%s%sです", FormatUtils.formatDateDisplay(today), description);
    }

    /**
     * 未設定ダイアログを表示する。
     * @param message
     */
    private void showPreferenceNotSetDialog(String message) {
        AlertDialog dialog = new AlertDialog.Builder(this).create();
        dialog.setMessage(message);
        dialog.setButton(AlertDialog.BUTTON_POSITIVE, "設定する", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                startActivity(new Intent(DashboardActivity.this, AppPreferenceActivity.class));
            }
        });
        dialog.show();
    }

    /**
     * @return ヘルプ表示ダイアログ
     */
    private AlertDialog createHelpDialog() {
        String versionName;
        try {
            PackageInfo packageInfo = getPackageManager().getPackageInfo(getPackageName(), PackageManager.GET_META_DATA);
            versionName = packageInfo.versionName;
        } catch (NameNotFoundException e) {
            versionName = "不明";
        }
        AlertDialog alertDialog = new AlertDialog.Builder(DashboardActivity.this).create();
        alertDialog.setMessage(String.format("Installed ver.%s\nサポートページに移動しますか？", versionName));
        alertDialog.setButton(AlertDialog.BUTTON_POSITIVE, getResources().getString(android.R.string.ok), new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                // サポートページに移動
                startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://sourceforge.jp/projects/schedulealarm/wiki/FrontPage")));
            }
        });
        alertDialog.setButton(AlertDialog.BUTTON_NEGATIVE, getResources().getString(android.R.string.cancel), new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.dismiss();
            }
        });
        return alertDialog;
    }

    /**
     * スケジュール一覧のアダプタを更新する。
     */
    private void refreshScheduleListAdapter() {
        Account account = AppAccountManager.getInstance(this).getAccount();
        if (account != null) {
            // アカウント設定済みなら更新する
            if (mCurrentAccount != account) {
                // アカウントが変更されていたら更新する
                mCurrentAccount = account;
                Cursor cursor = getContentResolver().query(DBHelper.URI_CALENDAR, new String[] { "_id", "title", "dtstart", "allDay" },
                        "_sync_account=? and dtstart>=strftime('%s', datetime('now','start of day')) || '000' and dtstart<=strftime('%s', datetime(datetime('now','start of day')),'7 days') || '000' and title like '%alarm%'", new String[] { account.name }, "dtstart");
                if (mScheduleListAdapter == null) {
                    // アダプタ未作成なら作成
                    SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_2, cursor, new String[] { "title", "dtstart" }, new int[] { android.R.id.text1, android.R.id.text2 });
                    adapter.setViewBinder(new SimpleCursorAdapter.ViewBinder() {
                        @Override
                        public boolean setViewValue(View view, Cursor cursor, int columnIndex) {
                            String text = null;
                            if (view.getId() == android.R.id.text1) {
                                // タイトル表示
                                text = cursor.getString(1);
                            } else if (view.getId() == android.R.id.text2) {
                                // 日時表示
                                Date d = new Date(cursor.getLong(2));
                                text = cursor.getString(1).contains("-alarm") ? FormatUtils.formatDateDisplay(d) : FormatUtils.formatDateTimeDisplay(d);
                            }
                            ((TextView) view).setText(text);
                            return true;
                        }
                    });
                    ((ListView) findViewById(R.id.schedule_list)).setAdapter(adapter);
                } else {
                    // アダプタ作成済なら更新
                    mScheduleListAdapter.changeCursor(cursor);
                }
            }
        }
    }
}
