/*
 *  Copyright (C) 2004-2012 Savoir-Faire Linux Inc.
 *
 *  Author: Adrien Beraud <adrien.beraud@gmail.com>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 *  Additional permission under GNU GPL version 3 section 7:
 *
 *  If you modify this program, or any covered work, by linking or
 *  combining it with the OpenSSL project's OpenSSL library (or a
 *  modified version of that library), containing parts covered by the
 *  terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
 *  grants you additional permission to convey the resulting work.
 *  Corresponding Source for a non-source form of such a combination
 *  shall include the source code for the parts of OpenSSL used as well
 *  as that of the covered work.
 */
package com.savoirfairelinux.sflphone.client;

import java.util.Random;

import android.app.ActionBar;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.RemoteException;
import android.support.v13.app.FragmentStatePagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.LinearInterpolator;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.TextView;

import com.savoirfairelinux.sflphone.R;
import com.savoirfairelinux.sflphone.service.ISipService;
import com.savoirfairelinux.sflphone.service.SipService;
import com.savoirfairelinux.sflphone.utils.AccountList;
import com.savoirfairelinux.sflphone.utils.CallList;

import java.util.HashMap;

public class SFLPhoneHome extends Activity implements ActionBar.TabListener, OnClickListener
{
    SectionsPagerAdapter mSectionsPagerAdapter = null;
    static final String TAG = "SFLPhoneHome";
    private static final int REQUEST_CODE_PREFERENCES = 1;
    ImageButton buttonCall, buttonHangup;
    static Animation animation;
    private ContactListFragment mContactListFragment = null;
    private CallElementList mCallElementList = null;
    private HistorySectionFragment mHistorySectionFragment = null;
    private ButtonSectionFragment mButtonSectionFragment = null;
    private boolean mBound = false;
    private ISipService service;
    public AccountList mAccountList;
    public CallList mCallList = new CallList(this);
    private SFLphoneApplication mApplication;

    private static final int ACTION_BAR_TAB_CONTACT = 0;
    private static final int ACTION_BAR_TAB_CALL = 1;
    private static final int ACTION_BAR_TAB_HISTORY = 2;
    private static final int ACTION_BAR_TAB_TEST = 3;

    /**
     * The {@link ViewPager} that will host the section contents.
     */
    ViewPager mViewPager;

    final private int[] icon_res_id = {R.drawable.ic_tab_call, R.drawable.ic_tab_call, R.drawable.ic_tab_history, R.drawable.ic_tab_play_selected};

    // public SFLPhoneHome extends Activity implements ActionBar.TabListener, OnClickListener

    /* called before activity is killed, e.g. rotation */
    @Override
    protected void onSaveInstanceState(Bundle bundle) {
        super.onSaveInstanceState(bundle);
        for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) {
            try {
                /* putFragment (Bundle bundle, String key, Fragment fragment) */
                getFragmentManager().putFragment(bundle, mSectionsPagerAdapter.getClassName(i), mSectionsPagerAdapter.getFragment(i));
            } catch (IllegalStateException e) {
                Log.e(TAG, "IllegalStateException: fragment=" + mSectionsPagerAdapter.getFragment(i));
            }
        }
        Log.w(TAG, "onSaveInstanceState()");
    }

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

        mApplication = (SFLphoneApplication) getApplication();

        // Bind to LocalService
        if (!mBound) {
            Log.i(TAG, "onStart: Binding service...");
            Intent intent = new Intent(this, SipService.class);
            bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
        }

        setContentView(R.layout.activity_sflphone_home);

        if (mSectionsPagerAdapter == null) {
            mSectionsPagerAdapter = new SectionsPagerAdapter(getFragmentManager());
        }

        /* getFragment(Bundle, String) */
        if (savedInstanceState != null) {
            Log.w(TAG, "Activity restarted, recreating PagerAdapter...");
            /* getFragment (Bundle bundle, String key) */
            mContactListFragment = (ContactListFragment) getFragmentManager().getFragment(
                    savedInstanceState, mSectionsPagerAdapter.getClassName(ACTION_BAR_TAB_CONTACT));
            mCallElementList = (CallElementList) getFragmentManager().getFragment(
                    savedInstanceState, mSectionsPagerAdapter.getClassName(ACTION_BAR_TAB_CALL));
            mHistorySectionFragment = (HistorySectionFragment) getFragmentManager().getFragment(
                    savedInstanceState, mSectionsPagerAdapter.getClassName(ACTION_BAR_TAB_HISTORY));
            mButtonSectionFragment = (ButtonSectionFragment) getFragmentManager().getFragment(
                    savedInstanceState, mSectionsPagerAdapter.getClassName(ACTION_BAR_TAB_TEST));
        }

        if (mContactListFragment == null) {
            mContactListFragment = new ContactListFragment();
            Log.w(TAG, "Recreated mContactListFragment=" + mContactListFragment);
        }
        if (mCallElementList == null) {
            mCallElementList = new CallElementList();
            Log.w(TAG, "Recreated mCallElementList=" + mCallElementList);
        }
        if (mHistorySectionFragment == null) {
            mHistorySectionFragment = new HistorySectionFragment();
            Log.w(TAG, "Recreated mHistorySectionFragment=" + mHistorySectionFragment);
        }
        if (mButtonSectionFragment == null) {
            mButtonSectionFragment = new ButtonSectionFragment();
            Log.w(TAG, "Recreated mButtonSectionFragment=" + mButtonSectionFragment);
        }

        final ActionBar actionBar = getActionBar();
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
        // final ActionBar actionBar = getActionBar();

        // Set up the ViewPager with the sections adapter.
        mViewPager = (ViewPager) findViewById(R.id.pager);
        mViewPager.setAdapter(mSectionsPagerAdapter);

        // When swiping between different sections, select the corresponding tab.
        // We can also use ActionBar.Tab#select() to do this if we have a reference to the
        // Tab.
        mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener()
        {
            @Override
            public void onPageSelected(int position)
            {
                actionBar.setSelectedNavigationItem(position);
            }
        });

        // For each of the sections in the app, add a tab to the action bar.
        for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) {
            // Create a tab with text corresponding to the page title defined by the adapter.
            // Also specify this Activity object, which implements the TabListener interface, as the
            // listener for when this tab is selected.
            Log.i(TAG, "adding tab: " + i);
            actionBar.addTab(actionBar.newTab().setIcon(icon_res_id[i]).setText(mSectionsPagerAdapter.getPageTitle(i)).setTabListener(this));
        }

        actionBar.setSelectedNavigationItem(ACTION_BAR_TAB_CALL);

        buttonCall = (ImageButton) findViewById(R.id.buttonCall);
        buttonHangup = (ImageButton) findViewById(R.id.buttonHangUp);

        // Change alpha from fully visible to invisible
        animation = new AlphaAnimation(1, 0);
        // duration - half a second
        animation.setDuration(500);
        // do not alter animation rate
        animation.setInterpolator(new LinearInterpolator());
        // Repeat animation infinitely
        animation.setRepeatCount(Animation.INFINITE);
        // Reverse
        animation.setRepeatMode(Animation.REVERSE);

        LocalBroadcastManager.getInstance(this).registerReceiver(mCallList, new IntentFilter("new-call-created"));
        LocalBroadcastManager.getInstance(this).registerReceiver(mCallList, new IntentFilter("call-state-changed"));
        LocalBroadcastManager.getInstance(this).registerReceiver(mCallList, new IntentFilter("incoming-call"));

        mAccountList = mApplication.getAccountList();

        LocalBroadcastManager.getInstance(this).registerReceiver(mAccountList, new IntentFilter("accounts-changed"));
        LocalBroadcastManager.getInstance(this).registerReceiver(mAccountList, new IntentFilter("account-state-changed"));

        SipCall.setSFLPhoneHomeContext(this);
    }

    @Override
    protected void onStart() {
        Log.i(TAG, "onStart");
        super.onStart();
    }

    /* user gets back to the activity, e.g. through task manager */
    @Override
    protected void onRestart() {
        super.onRestart();
    }

    /* activity gets back to the foreground and user input */
    @Override
    protected void onResume() {
        Log.i(TAG, "onResume");
        super.onResume();
    }

    /* activity no more in foreground */
    @Override
    protected void onPause() {
        super.onPause();
    }

    /* activity is no longer visible */
    @Override
    protected void onStop() {
        super.onStop();
    }

    /* activity finishes itself or is being killed by the system */
    @Override
    protected void onDestroy() {
        /* stop the service, if no other bound user, no need to check if it is running */
        if (mBound) {
            Log.i(TAG, "onStop: Unbinding service...");
            unbindService(mConnection);
            mBound = false;
        }
//        Log.i(TAG, "onDestroy: stopping SipService...");
//        stopService(new Intent(this, SipService.class));
//        mApplication.setServiceRunning(false);

        /* unregister broadcast receiver */
        LocalBroadcastManager.getInstance(this).unregisterReceiver(mCallList);
        LocalBroadcastManager.getInstance(this).unregisterReceiver(mAccountList);

        super.onDestroy();
    }
    
    /** Defines callbacks for service binding, passed to bindService() */
    private ServiceConnection mConnection = new ServiceConnection() {

        @Override
        public void onServiceConnected(ComponentName className,
                IBinder binder) {
            service = ISipService.Stub.asInterface(binder);
            mApplication.setSipService(service);
            mBound = true;
            mAccountList.setSipService(service);
            Log.d(TAG, "Service connected service=" + service);
        }

        @Override
        public void onServiceDisconnected(ComponentName arg0) {
            mApplication.setSipService(null);
            mBound = false;
            Log.w(TAG, "Service disconnected service=" + service);
        }
    };

//    private void startSipService() {
//        Thread thread = new Thread("StartSFLphoneService") {
//            public void run() {
//                Intent sipServiceIntent = new Intent(SFLPhoneHome.this, SipService.class);
//                //sipServiceIntent.putExtra(ServiceConstants.EXTRA_OUTGOING_ACTIVITY, new ComponentName(SFLPhoneHome.this, SFLPhoneHome.class));
//                startService(sipServiceIntent);
//                mApplication.setServiceRunning(true);
//            };
//        };
//        try {
//            thread.start();
//        } catch (IllegalThreadStateException e) {
//            AlertDialog.Builder builder = new AlertDialog.Builder(this);
//            builder.setMessage("Cannot start SFLPhone SipService!");
//            AlertDialog alert = builder.create();
//            alert.show();
//            finish();
//        }
//    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        Log.i("SFLphone", "onOptionsItemSelected " + item.getItemId());
        if(item.getItemId() != 0) {
            // When the button is clicked, launch an activity through this intent
            Intent launchPreferencesIntent = new Intent().setClass(this, SFLPhonePreferenceActivity.class);

            // Make it a subactivity so we know when it returns
            startActivityForResult(launchPreferencesIntent, REQUEST_CODE_PREFERENCES);
        }

        return super.onOptionsItemSelected(item);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu)
    {
        getMenuInflater().inflate(R.menu.activity_sflphone_home, menu);
        return true;
    }

    @Override
    public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction)
    {
    }

    @Override
    public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction)
    {
        // When the given tab is selected, switch to the corresponding page in the ViewPager.
        mViewPager.setCurrentItem(tab.getPosition());
    }

    @Override
    public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction)
    {
        //		Log.d(TAG, "onTabReselected");
    }

    public void onSelectedCallAction(SipCall call) {
        int callState = call.getCallStateInt();

        if((callState == SipCall.CALL_STATE_NONE) ||
           (callState == SipCall.CALL_STATE_CURRENT)) {
            buttonCall.setEnabled(false);
            buttonHangup.setEnabled(true);
        }
        else {
            buttonCall.setEnabled(true);
            buttonHangup.setEnabled(false);
        }

        buttonCall.setTag(call);
        buttonHangup.setTag(call);
    }

    public void onUnselectedCallAction() {
        buttonCall.setTag(null);
        buttonCall.setTag(null);

        buttonCall.setEnabled(true);
        buttonHangup.setEnabled(false);
    }

    public void setIncomingCallID(String accountID, String callID, String from) {
        Log.i(TAG, "incomingCall(" + accountID + ", " + callID + ", " + from + ")");
        buttonCall.startAnimation(animation);
        buttonCall.setImageResource(R.drawable.ic_incomingcall);
    }

    /**
     * A {@link FragmentStatePagerAdapter} that returns a fragment corresponding to
     * one of the primary sections of the app.
     */
    public class SectionsPagerAdapter extends FragmentStatePagerAdapter
    {

        public SectionsPagerAdapter(FragmentManager fm)
        {
            super(fm);
        }

        @Override
        public Fragment getItem(int i)
        {
            Fragment fragment;

            switch (i) {
            case 0:
                mContactListFragment = new ContactListFragment();
                fragment = mContactListFragment;
                break;
            case 1:
                mCallElementList = new CallElementList();
                SipCall.setCallElementList(mCallElementList);
                mCallElementList.setAccountList(mAccountList);
                fragment = mCallElementList;
                break;
            case 2:
                fragment = new HistorySectionFragment();
                break;
            case 3:
                fragment = new ButtonSectionFragment();
                Log.i(TAG, "getItem: fragment is " + fragment);
                break;
            default:
                Log.e(TAG, "getItem: unknown tab position " + i);
                return null;
            }

            Bundle args = new Bundle();
            args.putInt(HistorySectionFragment.ARG_SECTION_NUMBER, i + 1);
            fragment.setArguments(args);
            return fragment;
        }

        public Fragment getFragment(int i)
        {
            Fragment fragment;

            switch (i) {
            case 0:
                fragment = mContactListFragment;
                break;
            case 1:
                fragment = mCallElementList;
                break;
            case 2:
                fragment = mHistorySectionFragment;
                break;
            case 3:
                fragment = mButtonSectionFragment;
                break;
            default:
                Log.e(TAG, "getClassName: unknown fragment position " + i);
                fragment = null;
            }

//            Log.w(TAG, "getFragment: fragment=" + fragment);
            return fragment;
        }

        public String getClassName(int i)
        {
            String name;

            switch (i) {
            case 0:
                name = ContactListFragment.class.getName();
                break;
            case 1:
                name = CallElementList.class.getName();
                break;
            case 2:
                name = HistorySectionFragment.class.getName();
                break;
            case 3:
                name = ButtonSectionFragment.class.getName();
                break;
            default:
                Log.e(TAG, "getClassName: unknown fragment position " + i);
                return null;
            }

//            Log.w(TAG, "getClassName: name=" + name);
            return name;
        }

        @Override
        public int getCount()
        {
            return 4;
        }

        @Override
        public CharSequence getPageTitle(int position)
        {
            switch (position) {
            case 0:
                return getString(R.string.title_section0).toUpperCase();
            case 1:
                return getString(R.string.title_section1).toUpperCase();
            case 2:
                return getString(R.string.title_section2).toUpperCase();
            case 3:
                return getString(R.string.title_section3).toUpperCase();
            default:
                Log.e(TAG, "getPageTitle: unknown tab position " + position);
                break;
            }
            return null;
        }
    }

    /**
     * A dummy fragment representing a section of the app, but that simply
     * displays dummy text.
     */
    public static class HistorySectionFragment extends Fragment
    {
        public HistorySectionFragment()
        {
            setRetainInstance(true);
        }

        public static final String ARG_SECTION_NUMBER = "section_number";

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState)
        {
            TextView textView = new TextView(getActivity());
            textView.setGravity(Gravity.CENTER);
            Bundle args = getArguments();
            textView.setText(Integer.toString(args.getInt(ARG_SECTION_NUMBER)));
            textView.setText("java sucks");
            return textView;
        }
    }

    @Override
    public void onClick(View view)
    {
        Log.i(TAG, "onClic from SFLPhoneHome");
        switch (view.getId()) {
            case R.id.buttonCall:
                processingNewCallAction();
                break;
            case R.id.buttonHangUp:
                processingHangUpAction();
                break;
            default:
                Log.w(TAG, "unknown button " + view.getId());
                break;
        }
    }

    public void processingNewCallAction() {
        // String accountID = mAccountList.currentAccountID;
        String accountID = mCallElementList.getSelectedAccount();
        EditText editText = (EditText) findViewById(R.id.phoneNumberTextEntry);
        String to = editText.getText().toString();

        Random random = new Random();
        String callID = Integer.toString(random.nextInt());
        SipCall.CallInfo info = new SipCall.CallInfo();

        info.mCallID = callID;
        info.mAccountID = accountID;
        info.mDisplayName = "Cool Guy!";
        info.mPhone = to;
        info.mEmail = "coolGuy@coolGuy.com";
        info.mCallType = SipCall.CALL_TYPE_OUTGOING;

        SipCall call = CallList.getCallInstance(info);
        call.launchCallActivity(this);
        call.placeCallUpdateUi();
        call.notifyServicePlaceCall(service);
     
        onSelectedCallAction(call);
    }

    public void processingHangUpAction() {
        SipCall call = (SipCall)buttonHangup.getTag();
        if(call != null)
            call.notifyServiceHangup(service);
    }
}
