/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

package org.mozilla.gecko;

import android.content.Context;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.StateListDrawable;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TabHost;
import android.widget.TabWidget;

public class AwesomeBarTabs extends TabHost
                            implements LightweightTheme.OnChangeListener { 
    private static final String LOGTAG = "GeckoAwesomeBarTabs";

    private Context mContext;
    private GeckoActivity mActivity;

    private boolean mInflated;
    private LayoutInflater mInflater;
    private OnUrlOpenListener mUrlOpenListener;
    private View.OnTouchListener mListTouchListener;
    private boolean mSearching = false;
    private String mTarget;
    private ViewPager mViewPager;
    private AwesomePagerAdapter mPagerAdapter;

    private AwesomeBarTab mTabs[];

    public interface OnUrlOpenListener {
        public void onUrlOpen(String url, String title);
        public void onSearch(SearchEngine engine, String text);
        public void onEditSuggestion(String suggestion);
        public void onSwitchToTab(final int tabId);
    }

    private class AwesomePagerAdapter extends PagerAdapter {
        public AwesomePagerAdapter() {
            super();
        }

        @Override
        public Object instantiateItem(ViewGroup group, int index) {
            AwesomeBarTab tab = mTabs[index];
            group.addView(tab.getView());
            return tab;
        }

        @Override
        public void destroyItem(ViewGroup group, int index, Object obj) {
            AwesomeBarTab tab = (AwesomeBarTab)obj;
            group.removeView(tab.getView());
        }

        @Override
        public int getCount() {
            if (mSearching)
                return 1;
            return mTabs.length;
        }

        @Override
        public boolean isViewFromObject(View view, Object object) {
            return getAwesomeBarTabForView(view) == object;
        }
    }

    private AwesomeBarTab getCurrentAwesomeBarTab() {
        int index = mViewPager.getCurrentItem();
        return mTabs[index];
    }

    public AwesomeBarTab getAwesomeBarTabForView(View view) {
        String tag = (String)view.getTag();
        return getAwesomeBarTabForTag(tag);
    }

    public AwesomeBarTab getAwesomeBarTabForTag(String tag) {
        for (AwesomeBarTab tab : mTabs) {
            if (tag.equals(tab.getTag())) {
                return tab;
            }
        }
        return null;
    }

    public boolean onBackPressed() {
        AwesomeBarTab tab = getCurrentAwesomeBarTab();
        if (tab == null)
             return false;
        return tab.onBackPressed();
    }

    public AwesomeBarTabs(Context context, AttributeSet attrs) {
        super(context, attrs);

        Log.d(LOGTAG, "Creating AwesomeBarTabs");

        mContext = context;
        mActivity = (GeckoActivity) context;

        mInflated = false;
        mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

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

        // HACK: Without this, the onFinishInflate is called twice
        // This issue is due to a bug when Android inflates a layout with a
        // parent. Fixed in Honeycomb
        if (mInflated)
            return;

        mInflated = true;

        // This should be called before adding any tabs
        // to the TabHost.
        setup();

        mListTouchListener = new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent event) {
                if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
                    // take focus away from awesome bar to hide the keyboard
                    requestFocus();
                }
                return false;
            }
        };

        mTabs = new AwesomeBarTab[] {
            new AllPagesTab(mContext),
            new BookmarksTab(mContext),
            new HistoryTab(mContext)
        };

        final TabWidget tabWidget = (TabWidget) findViewById(android.R.id.tabs);
        // hide the strip since we aren't using the TabHost...
        tabWidget.setStripEnabled(false);

        mViewPager = (ViewPager) findViewById(R.id.tabviewpager);
        mPagerAdapter = new AwesomePagerAdapter();
        mViewPager.setAdapter(mPagerAdapter);

        mViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrollStateChanged(int state) { }
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { }
            @Override
            public void onPageSelected(int position) {
                tabWidget.setCurrentTab(position);
                styleSelectedTab();
                // take focus away from awesome bar to hide the keyboard
                requestFocus();
             }
         });

        for (int i = 0; i < mTabs.length; i++) {
            mTabs[i].setListTouchListener(mListTouchListener);
            addAwesomeTab(mTabs[i].getTag(),
                          mTabs[i].getTitleStringId(),
                          i);
        }

        // Initialize "All Pages" list with no filter
        filter("", null);
    }

    @Override
    public void onAttachedToWindow() {
        super.onAttachedToWindow();
        mActivity.getLightweightTheme().addListener(this);
    }

    @Override
    public void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        mActivity.getLightweightTheme().removeListener(this);
    }

    @Override
    public void onLightweightThemeChanged() {
        styleSelectedTab();
    }

    @Override
    public void onLightweightThemeReset() {
        styleSelectedTab();
    }

    public void setCurrentItemByTag(String tag) {
        mViewPager.setCurrentItem(getTabIdByTag(tag));
    }

    public int getTabIdByTag(String tag) {
        for (int i = 0; i < mTabs.length; i++) {
            if (tag.equals(mTabs[i].getTag())) {
                return i;
            }
        }
        return -1;
    }

    private void styleSelectedTab() {
        int selIndex = mViewPager.getCurrentItem();
        TabWidget tabWidget = getTabWidget();
        boolean isPrivate = false;

        if (mTarget != null && mTarget.equals(AwesomeBar.Target.CURRENT_TAB.name())) {
            Tab tab = Tabs.getInstance().getSelectedTab();
            if (tab != null)
                isPrivate = tab.isPrivate();
        }

        for (int i = 0; i < tabWidget.getTabCount(); i++) {
            GeckoTextView view = (GeckoTextView) tabWidget.getChildTabViewAt(i);
            if (isPrivate) {
                view.resetTheme();
                view.setPrivateMode((i == selIndex) ? false : true);
            } else {
                if (i == selIndex)
                    view.resetTheme();
                else if (mActivity.getLightweightTheme().isEnabled())
                    view.setTheme(mActivity.getLightweightTheme().isLightTheme());
                else
                    view.resetTheme();
            }

            if (i < (selIndex - 1))
                view.getBackground().setLevel(3);
            else if (i == (selIndex - 1))
                view.getBackground().setLevel(1);
            else if (i == (selIndex + 1))
                view.getBackground().setLevel(2);
            else if (i > (selIndex + 1))
                view.getBackground().setLevel(4);
        }

        if (selIndex == 0)
            findViewById(R.id.tab_widget_left).getBackground().setLevel(1);
        else
            findViewById(R.id.tab_widget_left).getBackground().setLevel(0);

        if (selIndex == (tabWidget.getTabCount() - 1))
            findViewById(R.id.tab_widget_right).getBackground().setLevel(2);
        else
            findViewById(R.id.tab_widget_right).getBackground().setLevel(0);
    }


    private View addAwesomeTab(String id, int titleId, final int contentId) {
        GeckoTextView indicatorView = (GeckoTextView) mInflater.inflate(R.layout.awesomebar_tab_indicator, null);
        indicatorView.setText(titleId);

        getTabWidget().addView(indicatorView);

        // this MUST be done after tw.addView to overwrite the listener added by tabWidget
        // which delegates to TabHost (which we don't have)
        indicatorView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mViewPager.setCurrentItem(contentId, true);
            }
        });

        return indicatorView;
    }

    public void setOnUrlOpenListener(OnUrlOpenListener listener) {
        mUrlOpenListener = listener;
        for (AwesomeBarTab tab : mTabs) {
            tab.setUrlListener(listener);
        }
    }

    public void destroy() {
        for (AwesomeBarTab tab : mTabs) {
            tab.destroy();
        }
    }

    public AllPagesTab getAllPagesTab() {
        return (AllPagesTab)getAwesomeBarTabForTag("allPages");
    }

    public BookmarksTab getBookmarksTab() {
        return (BookmarksTab)getAwesomeBarTabForTag("bookmarks");
    }

    public HistoryTab getHistoryTab() {
        return (HistoryTab)getAwesomeBarTabForTag("history");
    }

    public void filter(String searchTerm, AutocompleteHandler handler) {

        // If searching, disable left / right tab swipes
        mSearching = searchTerm.length() != 0;

        // reset the pager adapter to force repopulating the cache
        mViewPager.setAdapter(mPagerAdapter);

        // Ensure the 'All Pages' tab is selected
        AllPagesTab allPages = getAllPagesTab();
        getTabWidget().setCurrentTab(getTabIdByTag(allPages.getTag()));
        styleSelectedTab();

        // Perform the actual search
        allPages.filter(searchTerm, handler);

        // If searching, hide the tabs bar
        findViewById(R.id.tab_widget_container).setVisibility(mSearching ? View.GONE : View.VISIBLE);
    }

    public boolean isInReadingList() {
        return getBookmarksTab().isInReadingList();
    }

    public void setTarget(String target) {
        mTarget = target;
        styleSelectedTab();
        if (mTarget.equals(AwesomeBar.Target.CURRENT_TAB.name())) {
            Tab tab = Tabs.getInstance().getSelectedTab();
            if (tab != null && tab.isPrivate())
                ((BackgroundLayout) findViewById(R.id.tab_widget_container)).setPrivateMode(true);
        }
    }

    public static class BackgroundLayout extends GeckoLinearLayout {
        private GeckoActivity mActivity;

        public BackgroundLayout(Context context, AttributeSet attrs) {
            super(context, attrs);
            mActivity = (GeckoActivity) context;
        }

        @Override
        public void onLightweightThemeChanged() {
            LightweightThemeDrawable drawable = mActivity.getLightweightTheme().getColorDrawable(this);
            if (drawable == null)
                return;

            drawable.setAlpha(255, 0);

            StateListDrawable stateList = new StateListDrawable();
            stateList.addState(new int[] { R.attr.state_private }, new ColorDrawable(mActivity.getResources().getColor(R.color.background_private)));
            stateList.addState(new int[] {}, drawable);

            int[] padding =  new int[] { getPaddingLeft(),
                                         getPaddingTop(),
                                         getPaddingRight(),
                                         getPaddingBottom()
                                       };
            setBackgroundDrawable(stateList);
            setPadding(padding[0], padding[1], padding[2], padding[3]);
        }

        @Override
        public void onLightweightThemeReset() {
            int[] padding =  new int[] { getPaddingLeft(),
                                         getPaddingTop(),
                                         getPaddingRight(),
                                         getPaddingBottom()
                                       };
            setBackgroundResource(R.drawable.address_bar_bg);
            setPadding(padding[0], padding[1], padding[2], padding[3]);
        }
    }
}
