package jp.sourceforge.nicoro;

import android.app.Activity;
import android.content.Intent;
import android.content.res.Configuration;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.app.NavUtils;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;

import static jp.sourceforge.nicoro.Log.LOG_TAG;
import jp.gr.java_conf.shiseissi.commonlib.APILevelWrapper;
import jp.gr.java_conf.shiseissi.commonlib.ViewUtil;
import jp.sourceforge.nicoro.StaticRes.string;

public class MainFragmentActivity extends FragmentActivity
implements ListMenuUpdater, Handler.Callback, WebBrowserFragmentStarter,
ListMenuStarter, StartPlaylistDialogFragment.EventListener {
    private static final boolean DEBUG_LOGD = Release.IS_DEBUG & true;

//    public static final String INTENT_EXTRA_MAIN_PANE_TYPE = "MAIN_PANE_TYPE";
//    public static final int MAIN_PANE_TYPE_BROWSER = 0;
//    public static final int MAIN_PANE_TYPE_LISTMENU = 1;

    private static final int MSG_ID_START_BROWSER = 1;
    private static final int MSG_ID_START_LISTMENU = 2;

    static final String KEY_SHOW_LIST_MENU_IN_DUAL_PANE = "ShowListMenuInDualPane";

    private Configuration mCurrentConfig;
    private boolean mIsDualPane;
    private boolean mReservePaneChange;
    private boolean mResumed = false;
    private boolean mShowListMenuInDualPane;
    private boolean mSavedInstanceState;

    private Bundle mBundleListMenu;

    private ViewGroup mViewPaneListMenu;
    private ListMenuView mListMenuView;

    private MenuItem mOptionsMenuListMenu;

    private final HandlerWrapper mHandler = new HandlerWrapper(this);

    @Override
    public boolean handleMessage(Message msg) {
        switch (msg.what) {
            case MSG_ID_START_BROWSER:
                String url = (String) msg.obj;
                updateWebBrowserUrl(url);
                break;
            case MSG_ID_START_LISTMENU:
                Bundle bundle = (Bundle) msg.obj;
                updateListMenu(bundle);
                break;
        }
        return true;
    }

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

        mCurrentConfig = new Configuration(getResources().getConfiguration());
        updateIsDualPane(mCurrentConfig);

        setContentView(R.layout.main_fragment);
        mViewPaneListMenu = ViewUtil.findViewById(this, R.id.pane_listmenu);
        Intent intent = getIntent();
        FragmentManager manager = getSupportFragmentManager();

        WebBrowserFragment webBrowserFragment;
        if (savedInstanceState == null) {
            if (mIsDualPane) {
                createListMenuView();

                // TODO ここでのintentそのまま使って良かったどうか
                mListMenuView.updateListMenu(intent);

                // 明示的に後からcheckしてFragment生成
                mListMenuView.checkDefaultListRadio();

                webBrowserFragment = new WebBrowserFragment();
                manager.beginTransaction()
                    .add(R.id.pane_main, webBrowserFragment,
                            string.tag_webbrowser_fragment)
                    .commit();
                mShowListMenuInDualPane = true;
            } else {
                webBrowserFragment = new WebBrowserFragment();
                Fragment mainFragment = webBrowserFragment;
                String tag = string.tag_webbrowser_fragment;
                manager.beginTransaction()
                    .add(R.id.pane_main, mainFragment, tag)
                    .commit();
                mShowListMenuInDualPane = false;
            }
        } else {
            if (mIsDualPane) {
                createListMenuView();
            }

            FragmentTransaction transaction = manager.beginTransaction();
            webBrowserFragment = ViewUtil.findFragmentByTag(manager,
                    string.tag_webbrowser_fragment);
            if (webBrowserFragment == null) {
                webBrowserFragment = new WebBrowserFragment();
                transaction.add(R.id.pane_main, webBrowserFragment,
                        string.tag_webbrowser_fragment);
            }
            transaction.commit();

            mShowListMenuInDualPane = savedInstanceState.getBoolean(
                    KEY_SHOW_LIST_MENU_IN_DUAL_PANE, mIsDualPane);
        }
        int listMenuVisibility;
        if (mShowListMenuInDualPane) {
            listMenuVisibility = View.VISIBLE;
        } else {
            listMenuVisibility = View.GONE;
        }
        mViewPaneListMenu.setVisibility(listMenuVisibility);

        if (webBrowserFragment != null) {
            if (savedInstanceState == null) {
                // TODO Intentこの形式のままでいいのか？
                String url = getUrlFromIntentActionView(intent);
                webBrowserFragment.setStartUrl(url);
            }
        }

        mBundleListMenu = intent.getExtras();

        mOptionsMenuListMenu = null;
    }

    @Override
    protected void onStart() {
        super.onStart();
        mSavedInstanceState = false;

        APILevelWrapper api = APILevelWrapper.createInstance();
        api.setDisplayHomeAsUpEnabled_ActionBar(api.getActionBar(this), true);
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        setIntent(intent);
        mBundleListMenu = intent.getExtras();

        String url = getUrlFromIntentActionView(intent);
        if (url != null) {
            updateWebBrowserUrl(url);
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        mResumed = true;

        // 表示直後のIntent処理はFragment側から行う

        if (mReservePaneChange) {
            reflectPaneChange();
            mReservePaneChange = false;
        }

        if (mListMenuView != null) {
            mListMenuView.updateAllListMenu(this);
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        mResumed = false;

        if (mListMenuView != null) {
            mListMenuView.setCurrentRadioToDefaultRadio();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putBoolean(KEY_SHOW_LIST_MENU_IN_DUAL_PANE,
                mShowListMenuInDualPane);
        mSavedInstanceState = true;
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        // 1.6向けなのでonKeyDownでback key監視
        // onBackPressedの活用は、API5からのため駄目
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            Fragment fragment = ViewUtil.findFragmentById(
                    getSupportFragmentManager(),
                    R.id.pane_main);
            if (fragment instanceof WebBrowserFragment) {
                if (((WebBrowserFragment) fragment).goBackWebView()) {
                    return true;
                }
            }
        }
        // TODO 何故かFragmentManagerImplでIllegalStateException起きるときがある？
        return super.onKeyDown(keyCode, event);
    }

    void updateListMenu(Bundle bundle) {
//        if (mSavedInstanceState) {
//            if (DEBUG_LOGD) {
//                Log.d(LOG_TAG, "after onSaveInstanceState, ignore MainFragmentActivity#updateListMenu");
//            }
//            return;
//        }

        if (mIsDualPane) {
            updateFragmentBookmarks(bundle);
            updateFragmentRelatedVideo(bundle);
            updateFragmentListMenu(bundle);
        } else {
            Intent intent = new Intent(this, ListMenuActivity.class)
                .setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
            intent.replaceExtras(bundle);
            startActivity(intent);
        }
    }

    void updateFragmentBookmarks(Bundle bundle) {
        BookmarksFragment bookmarks = findFragmentInListMenu(
                BookmarksFragment.class);
        ListMenuView.updateFragmentBookmarks(bundle, bookmarks);
    }

    void updateFragmentRelatedVideo(Bundle bundle) {
        RelatedVideoFragment relatedVideo = findFragmentInListMenu(
                RelatedVideoFragment.class);
        ListMenuView.updateFragmentRelatedVideo(bundle, relatedVideo);
    }
    void updateFragmentListMenu(Bundle bundle) {
        assert mListMenuView != null;
        mListMenuView.updateListMenu(bundle);
    }

    public <T extends Fragment> T findFragmentInListMenu(Class<T> clz) {
        if (mListMenuView == null) {
            return null;
        } else {
            return mListMenuView.findFragment(clz);
        }
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        boolean lastIsDualPane = mIsDualPane;
        updateIsDualPane(newConfig);
        mCurrentConfig.updateFrom(newConfig);

        if (lastIsDualPane != mIsDualPane) {
            if (mResumed) {
                reflectPaneChange();
            } else {
                mReservePaneChange = true;
            }
            updateOptionsMenu();
        }

        if (mListMenuView != null) {
            mListMenuView.onOrientationChanged(newConfig.orientation, mIsDualPane);
        }
    }

    private void reflectPaneChange() {
        int listMenuVisibility;
        if (mIsDualPane) {
            if (mShowListMenuInDualPane) {
                listMenuVisibility = View.VISIBLE;
            } else {
                listMenuVisibility = View.GONE;
            }
            if (mListMenuView == null) {
                createListMenuView();
                // TODO 空のBundle作るのはちょっと無駄
                mListMenuView.updateListMenu(new Bundle());
                // 明示的に後からcheckしてFragment生成
                mListMenuView.checkDefaultListRadio();
            }
        } else {
            listMenuVisibility = View.GONE;
        }
        mViewPaneListMenu.setVisibility(listMenuVisibility);
    }

    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        if (mOptionsMenuListMenu == null) {
            mOptionsMenuListMenu = menu.findItem(R.id.menu_list_menu);
            assert mOptionsMenuListMenu != null;
        }
        updateOptionsMenu();
        return super.onPrepareOptionsMenu(menu);
    }

    private void updateOptionsMenu() {
        if (mOptionsMenuListMenu == null) {
            return;
        }

        String listMenuTitle = getString(R.string.menu_list_menu);
        if (mIsDualPane) {
            if (mShowListMenuInDualPane) {
                listMenuTitle += " OFF";
            } else {
                listMenuTitle += " ON";
            }
        }
        if (!listMenuTitle.equals(mOptionsMenuListMenu.getTitle())) {
            mOptionsMenuListMenu.setTitle(listMenuTitle);
        }
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.menu_list_menu:
                if (mIsDualPane) {
                    // リストメニューON/OFF切り替え
//                    int lastVisibility = mViewPaneListMenu.getVisibility();
                    int newVisibility;
//                    if (lastVisibility == View.VISIBLE) {
                    if (mShowListMenuInDualPane) {
                        newVisibility = View.GONE;
                        mShowListMenuInDualPane = false;
                    } else {
                        newVisibility = View.VISIBLE;
                        mShowListMenuInDualPane = true;

                        if (mListMenuView == null) {
                            createListMenuView();
                            // TODO 空のBundle作るのはちょっと無駄
                            mListMenuView.updateListMenu(new Bundle());
                            // 明示的に後からcheckしてFragment生成
                            mListMenuView.checkDefaultListRadio();
                        }
                    }
                    mViewPaneListMenu.setVisibility(newVisibility);
                    updateOptionsMenu();
                    return true;
                }
                break;
            case android.R.id.home:
                NavUtils.navigateUpFromSameTask(this);
                return true;
        }
        return super.onOptionsItemSelected(item);
    }

    public static boolean isDualPane(Configuration config) {
        return (config.orientation == Configuration.ORIENTATION_LANDSCAPE
                && ((config.screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK)
                        >= Configuration.SCREENLAYOUT_SIZE_LARGE));
    }
    private void updateIsDualPane(Configuration config) {
        mIsDualPane = isDualPane(config);
    }

    void updateWebBrowserUrl(String url) {
        FragmentManager manager = getSupportFragmentManager();
        if (mIsDualPane) {
            WebBrowserFragment webBrowserFragment =
                ViewUtil.findFragmentByTag(manager,
                        string.tag_webbrowser_fragment);
            webBrowserFragment.updateCurrentUrl(url);
        } else {
            Fragment fragment = ViewUtil.findFragmentById(
                    manager, R.id.pane_main);
            if (fragment instanceof WebBrowserFragment) {
                ((WebBrowserFragment) fragment).updateCurrentUrl(url);
            } else {
                if (mSavedInstanceState) {
                    if (DEBUG_LOGD) {
                        Log.d(LOG_TAG, "after onSaveInstanceState, ignore MainFragmentActivity#updateWebBrowserUrl");
                    }
                } else {
                    FragmentTransaction transaction = manager.beginTransaction();
                    WebBrowserFragment webBrowserFragment =
                        ViewUtil.findFragmentByTag(manager,
                                string.tag_webbrowser_fragment);
                    if (webBrowserFragment == null) {
                        webBrowserFragment = new WebBrowserFragment();
                        webBrowserFragment.setStartUrl(url);
                        transaction.addToBackStack(null)
                            .add(R.id.pane_main, webBrowserFragment,
                                    string.tag_webbrowser_fragment);
                    } else {
                        webBrowserFragment.updateCurrentUrl(url);
                        transaction.addToBackStack(null)
                            .remove(webBrowserFragment)
                            .add(R.id.pane_main, webBrowserFragment,
                                    string.tag_webbrowser_fragment);
                    }
                    transaction.commit();
                }
            }
        }
    }

    public static void startBrowserActivity(Activity activity, String url) {
        Intent intent;
        if (url == null) {
            intent = new Intent(activity, MainFragmentActivity.class);
        } else {
            intent = new Intent(
                    Intent.ACTION_VIEW,
                    Uri.parse(url),
                    activity, MainFragmentActivity.class)
                .addCategory(Intent.CATEGORY_BROWSABLE);
        }
        intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
//        intent.putExtra(INTENT_EXTRA_MAIN_PANE_TYPE, MAIN_PANE_TYPE_BROWSER);
        activity.startActivity(intent);
    }

    public static void startListMenuActivity(Activity activity, int idListMenu) {
        Configuration config = activity.getResources().getConfiguration();
        Intent intent;
        if (isDualPane(config)) {
            intent = new Intent(activity, MainFragmentActivity.class);
        } else {
            intent = new Intent(activity, ListMenuActivity.class);
//            intent = new Intent(activity, MainFragmentActivity.class);
//            intent.putExtra(MainFragmentActivity.INTENT_EXTRA_MAIN_PANE_TYPE,
//                    MainFragmentActivity.MAIN_PANE_TYPE_LISTMENU);
        }
        intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
        if (idListMenu != 0) {
            intent.putExtra(ListMenuActivity.INTENT_EXTRA_DEFAULT_LIST_RADIO,
                    idListMenu);
        }
        activity.startActivity(intent);
    }

    @Override
    public Bundle getExtrasForListMenu() {
        Bundle ret = mBundleListMenu;
        // TODO 二重更新いやなのでいったん消す
        mBundleListMenu = null;
        return ret;
    }

    public static String getUrlFromIntentActionView(Intent intent) {
        if (intent == null) {
            return null;
        }
        if (Intent.ACTION_VIEW.equals(intent.getAction())) {
            Uri uri = intent.getData();
            if (uri != null) {
                return uri.toString();
            }
        }
        return null;
    }

    private void createListMenuView() {
        if (mViewPaneListMenu.getChildCount() != 0) {
            mViewPaneListMenu.removeAllViews();
        }

        LayoutInflater inflater = LayoutInflater.from(this);
        inflater.inflate(R.layout.list_menu, mViewPaneListMenu);
        mListMenuView = ViewUtil.findViewById(mViewPaneListMenu,
                R.id.list_menu_root);

        mListMenuView.onCreateView(inflater);
        mListMenuView.setFragmentManager(getSupportFragmentManager());
        mListMenuView.setIntent(getIntent());
        mListMenuView.onOrientationChanged(mCurrentConfig.orientation,
                mIsDualPane);
    }

    @Override
    public void startWebBrowserFragment(String url) {
        mHandler.obtainMessage(MSG_ID_START_BROWSER, url).sendToTarget();
    }

    @Override
    public void startListMenu(Bundle bundle) {
        mHandler.obtainMessage(MSG_ID_START_LISTMENU, bundle).sendToTarget();
    }

    /**
     * Auto Test向け
     * @return
     */
    boolean isDualPane() {
        return mIsDualPane;
    }

    /**
     * Auto Test向け
     * @return
     */
    boolean showListMenuInDualPane() {
        return mShowListMenuInDualPane;
    }

    @Override
    public void onStartPlaylistExecuted(StartPlaylistDialogFragment fragment) {
        WebBrowserFragment webBrowserFragment = ViewUtil.findFragmentByTag(
                getSupportFragmentManager(), string.tag_webbrowser_fragment);
        if (webBrowserFragment != null) {
            webBrowserFragment.onStartPlayerByOther();
        }
    }
}
