/**
 * Copyright (C) 2010-2012 Regis Montoya (aka r3gis - www.r3gis.fr)
 * This file is part of CSipSimple.
 *
 *  CSipSimple 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.
 *  If you own a pjsip commercial license you can also redistribute it
 *  and/or modify it under the terms of the GNU Lesser General Public License
 *  as an android library.
 *
 *  CSipSimple 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 CSipSimple.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.csipsimple.ui.outgoingcall;

import android.annotation.TargetApi;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.net.Uri;
import android.os.Bundle;
import android.os.IBinder;
import android.text.TextUtils;
import android.view.KeyEvent;

import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.csipsimple.R;
import com.csipsimple.api.ISipService;
import com.csipsimple.api.SipManager;
import com.csipsimple.api.SipProfile;
import com.csipsimple.utils.Compatibility;
import com.csipsimple.utils.Log;
import com.csipsimple.utils.PreferencesProviderWrapper;
import com.csipsimple.utils.UriUtils;

public class OutgoingCallChooser extends SherlockFragmentActivity {


    private static final String THIS_FILE = "OutgoingCallChooser";
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        resetInternals();
        
        // Sanity check
        if (TextUtils.isEmpty(getPhoneNumber())) {
            Log.e(THIS_FILE, "No number detected for : " + getIntent().getAction());
            finish();
            return;
        }
        setContentView(R.layout.outgoing_call_view);
        connectService();
    }
    
    private String phoneNumber = null;
    private boolean ignoreRewritingRules = false;
    private Long accountToCallTo = null;
    private Boolean callAutomatically = null;
    
    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        resetInternals();
    }
    
    private final static String SCHEME_CSIP = SipManager.PROTOCOL_CSIP;
    
    /**
     * Get the phone number that raised this activity.
     * @return The phone number we are trying to call with this activity
     */
    public String getPhoneNumber() {
        if(phoneNumber == null) {
            Intent it = getIntent();
            // Use utility function to extract number
            phoneNumber = UriUtils.extractNumberFromIntent(it, this);
            
            // Additional check to know if a csip uri (so that no rewriting rules applies)
            if (phoneNumber != null) {
                String action = it.getAction();
                Uri data = it.getData();
                if(!Intent.ACTION_SENDTO.equalsIgnoreCase(action) && data != null) {
                    String scheme = data.getScheme();
                    if(scheme != null) {
                        scheme = scheme.toLowerCase();
                    }
                    if(SCHEME_CSIP.equals(scheme)) {
                        ignoreRewritingRules = true;
                    }
                }
            }
            // Still null ... well make it empty.
            if(phoneNumber == null) {
                phoneNumber = "";
            }
            return phoneNumber;
        }
        
        return phoneNumber;
    }
    
    /**
     * Should we ignore rewriting rules
     * @return True if rewriting rules are not taken into account for this outgoing call.
     */
    public boolean shouldIgnoreRewritingRules() {
        // Ignore rewriting rule is get once phone number is retrieved
        getPhoneNumber();
        
        return ignoreRewritingRules;
    }
    
    /**
     * Get the account to force use for outgoing.
     * @return The account id to use for outgoing. {@link SipProfile#INVALID_ID} if no account should be used.
     */
    public long getAccountToCallTo() {
        if(accountToCallTo == null) {
            accountToCallTo = getIntent().getLongExtra(SipProfile.FIELD_ACC_ID, SipProfile.INVALID_ID);
        }
        return accountToCallTo;
    }

    /**
     * Should we allow automatic calls of others accounts
     * @return True if we can call automatically some accounts.
     */
    public boolean canCallAutomatically() {
        if(callAutomatically == null) {
            if(getAccountToCallTo() == SipProfile.INVALID_ID) {
                // No account specified, we can call automatically
                callAutomatically = true;
            }else {
                int fallbackBehavior = getIntent().getIntExtra(SipManager.EXTRA_FALLBACK_BEHAVIOR, SipManager.FALLBACK_ASK);
                if(fallbackBehavior == SipManager.FALLBACK_AUTO_CALL_OTHER) {
                    // The other app explicitely asked to fallback to other
                    callAutomatically = true;
                }else {
                    callAutomatically = false;
                }
            }
        }
        return callAutomatically;
    }
    
    /* Service connection */
    /**
     * Connect to sip service by flagging itself as the component to consider as outgoing activity
     */
    private void connectService() {
        PreferencesProviderWrapper prefsWrapper = new PreferencesProviderWrapper(this);
        Intent sipService = new Intent(SipManager.INTENT_SIP_SERVICE);
        // Optional, but here we bundle so just ensure we are using csipsimple package
        sipService.setPackage(getPackageName());
        if (prefsWrapper.isValidConnectionForOutgoing()) {
            sipService.putExtra(SipManager.EXTRA_OUTGOING_ACTIVITY, getComponentName());
            startService(sipService);
        }
        bindService(sipService, connection, Context.BIND_AUTO_CREATE);
    }
    /**
     * Get connected sip service.
     * @return connected sip service from the activity if already connected. Null else.
     */
    public ISipService getConnectedService() {
        return service;
    }
    
    private ISipService service = null;
    private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName component, IBinder binder) {
            service = ISipService.Stub.asInterface(binder);
        }

        @Override
        public void onServiceDisconnected(ComponentName arg0) {
            service = null;
        }
    };
    
    @TargetApi(5)
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK
                && event.getRepeatCount() == 0
                && !Compatibility.isCompatible(5)) {
            onBackPressed();

        }
        return super.onKeyDown(keyCode, event);
    }

    public void onBackPressed() {
        finishServiceIfNeeded(false);
    }
    
    /**
     * Finish the activity and send unregistration to service as outgoing activity.
     * @param defer If true the activity will ask sip service to remain active until end of next call (because it will initiate a call).
     * If false, ask sip service to consider outgoing mode as not anymore valid right now. Usually cause call will be managed another way than a sip way.
     */
    public void finishServiceIfNeeded(boolean defer) {
        Intent intent = new Intent(defer ? SipManager.ACTION_DEFER_OUTGOING_UNREGISTER : SipManager.ACTION_OUTGOING_UNREGISTER);
        intent.putExtra(SipManager.EXTRA_OUTGOING_ACTIVITY, getComponentName());
        sendBroadcast(intent);
        finish();
    }
    
    @Override
    protected void onDestroy() {
        super.onDestroy();
        resetInternals();
        try {
            unbindService(connection);
        } catch (Exception e) {
        }
    }
    
    private void resetInternals() {
        phoneNumber = null;
        accountToCallTo = null;
        ignoreRewritingRules = false;
        callAutomatically = null;
    }

}