/**
 * 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.voiceblue.phone.wizards.impl;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Toast;

import com.voiceblue.phone.R;
import com.voiceblue.phone.api.SipProfile;
import com.voiceblue.phone.utils.Log;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.lang.ref.WeakReference;
import java.net.Socket;
import java.net.URL;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class MondotalkCreate extends Activity implements OnClickListener, TextWatcher {
    
    private final static String API_KEY = "{7EB11554-7BAD-D25D-1D17-B070D4AC459F}";

    private static final String THIS_FILE = "MondotalkCreate";
    
    private ImageView captchaImg;
    private View captchaProgress;
    private EditText firstName;
    private EditText lastName;
    private EditText emailAddr;
    private EditText countryCode;
    private EditText phone;
    private EditText captcha;

    private ProgressDialog progressDialog;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        setContentView(R.layout.w_mondotalk_create);
        
        findViewById(R.id.cancel_bt).setOnClickListener(this);
        findViewById(R.id.save_bt).setOnClickListener(this);
        
        captchaImg = (ImageView) findViewById(R.id.cw_captcha_img);
        captchaProgress = findViewById(R.id.cw_captcha_progress);
        
        firstName = (EditText) findViewById(R.id.cw_first_name); 
        lastName = (EditText) findViewById(R.id.cw_last_name);
        emailAddr = (EditText) findViewById(R.id.cw_email);
        countryCode = (EditText) findViewById(R.id.cw_country_code);
        phone = (EditText) findViewById(R.id.cw_phone);
        captcha = (EditText) findViewById(R.id.cw_captcha);
        
        
        firstName.addTextChangedListener(this);
        emailAddr.addTextChangedListener(this);
        captcha.addTextChangedListener(this);
        
        // Ok, crappy thread creation to retrieve captcha in bg
        Thread t = new Thread() {
            public void run() {
                retrieveCaptcha();
            };
        };
        t.start();
        
        canSave();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if(captchaBitmap != null) {
            captchaBitmap.recycle();
        }
    }

    @Override
    public void onClick(View v) {
        int id = v.getId();
        if(id == R.id.cancel_bt) {
            setResult(RESULT_CANCELED);
            finish();
        }else if(id == R.id.save_bt) {
            if(canSave()) {
                progressDialog = ProgressDialog.show(this, getResources().getText(R.string.create_account), 
                        getResources().getText(R.string.loading), true);
                Thread t = new Thread() {
                    public void run() {
                        saveOnline(getEditTextValue(firstName), getEditTextValue(lastName),
                                getEditTextValue(emailAddr), getEditTextValue(phone),
                                getEditTextValue(countryCode), getEditTextValue(captcha));

                    };
                };
                t.start();
            }
        }
    }
    
    private final static int MSG_CAPTCHA_LOADED = 0;
    private final static int MSG_SAVE_DONE = 1;
    private final static int MSG_SAVE_ERROR = 2;

    private Handler mHander = new MondotalkHandler(this);
    
    private static class MondotalkHandler extends Handler {
        
        WeakReference<MondotalkCreate> w;
        
        MondotalkHandler(MondotalkCreate wizard){
            w = new WeakReference<MondotalkCreate>(wizard);
        }
        
        public void dispatchMessage(Message msg) {
            MondotalkCreate wizard = w.get();
            if(wizard == null) {
                return;
            }
            switch (msg.what) {
                case MSG_CAPTCHA_LOADED:
                    if(wizard.captchaBitmap != null && wizard.captchaImg != null) {
                        wizard.captchaImg.setImageBitmap(wizard.captchaBitmap);
                        wizard.captchaImg.setVisibility(View.VISIBLE);
                        wizard.captchaProgress.setVisibility(View.GONE);
                    }
                    break;
                case MSG_SAVE_DONE:
                    if(wizard.progressDialog != null) {
                        wizard.progressDialog.dismiss();
                    }
                    AccountCreationResult res = (AccountCreationResult) msg.obj;
                    Intent it = wizard.getIntent();
                    it.putExtra(SipProfile.FIELD_USERNAME, res.username);
                    it.putExtra(SipProfile.FIELD_DATA, res.password);
                    wizard.setResult(RESULT_OK, it);
                    wizard.finish();
                    break;
                case MSG_SAVE_ERROR:
                    if(wizard.progressDialog != null) {
                        wizard.progressDialog.dismiss();
                    }
                    Toast toast = Toast.makeText(wizard, (String)msg.obj, Toast.LENGTH_LONG);
                    toast.show();
                    break;
            }
        };
    };
    
    
    private String captchaKey = "";
    private String captchaUrl = "";
    private Bitmap captchaBitmap = null;

    private Pattern soapResultPattern = Pattern.compile("^.*<result xsi:type=\"xsd:string\">(.*)</result>.*$");
    private boolean retrieveCaptcha() {
        String ip;
        try {
            Socket socket = new Socket("api001.mondotalk.com", 80);
            ip = socket.getLocalAddress().toString();
        } catch (Exception e) {
            Log.e(THIS_FILE,"Can't get local ip address", e);
            ip = "127.0.0.1";
        }
        
        try {
            // No SOAP lib.... bourrinage !
            String requestURL = "https://api001.mondotalk.com/webservices/captcha.php";

            HttpPost httpPost = new HttpPost(requestURL);
            httpPost.addHeader("SOAPAction", "\"Captcha\"");
            httpPost.addHeader("Content-Type", "text/xml");

            // prepare POST body
            String body = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
                    "<SOAP-ENV:Envelope " +
                    " SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\" " +
                    " xmlns:SOAP-ENC=\"http://schemas.xmlsoap.org/soap/encoding/\"" +
                    " xmlns:xsi=\"http://www.w3.org/1999/XMLSchema-instance\" " +
                    " xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\"" +
                    " xmlns:xsd=\"http://www.w3.org/1999/XMLSchema\" >" +
                    "<SOAP-ENV:Body>" +
                    "<Captcha SOAP-ENC:root=\"1\">" +
                    "<v1 xsi:type=\"xsd:string\">" + API_KEY + "</v1>" +
                    "<v2 xsi:type=\"xsd:string\">" + ip + "</v2>" +
                    "<v3 xsi:type=\"xsd:string\">520</v3>" +
                    "<v4 xsi:type=\"xsd:string\">200</v4>" +
                    "</Captcha>" +
                    "</SOAP-ENV:Body>" +
                    "</SOAP-ENV:Envelope>";

            // set POST body
            HttpEntity entity;
            entity = new StringEntity(body);
            httpPost.setEntity(entity);
            

            HttpClient httpClient = new DefaultHttpClient();
            // Create a response handler
            HttpResponse httpResponse = httpClient.execute(httpPost);
            if(httpResponse.getStatusLine().getStatusCode() == 200) {
                InputStreamReader isr = new InputStreamReader(httpResponse.getEntity().getContent());
                BufferedReader br = new BufferedReader(isr);

                String line = null;
                while( (line = br.readLine() ) != null ) {
                    if(!TextUtils.isEmpty(line)) {

                        Matcher matcher = soapResultPattern.matcher(line);
                        if(matcher.matches()) {
                            String strValue = matcher.group(1).trim();
                            if(!TextUtils.isEmpty(strValue)) {
                                String[] strValues = strValue.split("\\|");
                                if(strValues.length > 1) {
                                    captchaUrl = strValues[0];
                                    captchaKey = strValues[1];
                                }
                            }
                            break;
                        }
                    }
                }
                
                if(TextUtils.isEmpty(captchaKey)) {
                    return false;
                }
                
                Log.d(THIS_FILE, "Captcha retrieved " + captchaKey + " and " + captchaUrl);
                
                captchaBitmap = BitmapFactory.decodeStream((new URL(captchaUrl)).openConnection() .getInputStream()); 
                
                mHander.sendEmptyMessage(MSG_CAPTCHA_LOADED);
            }else {
                Log.e(THIS_FILE, "Something went wrong while retrieving the captcha webservice ");
            }

        } catch (Exception e) {
            Log.e(THIS_FILE, "Something went wrong while retrieving the captcha", e);
        }
        
        return false;
    }
    
    /**
     * Client side form validation.
     * 
     * @return true if the form is valid for save
     */
    private boolean canSave() {
        boolean isValid = true;
        
        isValid &= checkEmptyText(firstName);
        isValid &= checkEmptyText(emailAddr);
        isValid &= checkEmptyText(captcha);
        
        
        // Update the status of the save button
        findViewById(R.id.save_bt).setEnabled(isValid);
        
        return isValid;
    }
    
    /**
     * Get the value of an edit text a safe way
     * @param txt The edit text to get value of
     * @return the Text value of the edit text
     */
    private String getEditTextValue(EditText txt) {
        if(txt == null) {
            return "";
        }
        String res = txt.getText().toString();
        if(TextUtils.isEmpty(res)) {
            return "";
        }
        return res;
    }
    private boolean checkEmptyText(EditText txt) {
        if(TextUtils.isEmpty(txt.getText().toString())) {
            txt.setError("Empty");
            return false;
        }
        txt.setError(null);
        return true;
    }
    
    
    private class AccountCreationResult {
        final String username;
        final String password;
        AccountCreationResult(String uname, String pwd){
            username = uname;
            password = pwd;
        }
    }
    
    private boolean saveOnline(String firstName, String lastName, String contactEmail, String contactPhone, String countryCode, String captcha) {

        try {
            // No SOAP lib.... bourrinage !
            String requestURL = "https://api001.mondotalk.com/webservices/createaccount.php";

            HttpPost httpPost = new HttpPost(requestURL);
            httpPost.addHeader("SOAPAction", "\"CreateAccount\"");
            httpPost.addHeader("Content-Type", "text/xml");

            // prepare POST body
            String body = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
                    "<SOAP-ENV:Envelope " +
                    " SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\" " +
                    " xmlns:SOAP-ENC=\"http://schemas.xmlsoap.org/soap/encoding/\"" +
                    " xmlns:xsi=\"http://www.w3.org/1999/XMLSchema-instance\" " +
                    " xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\"" +
                    " xmlns:xsd=\"http://www.w3.org/1999/XMLSchema\" >" +
                    "<SOAP-ENV:Body>" +
                    "<CreateAccount SOAP-ENC:root=\"1\">" +
                    "<v1 xsi:type=\"xsd:string\">" + API_KEY + "</v1>" +
                    "<v2 xsi:type=\"xsd:string\">" + firstName + "</v2>" +
                    "<v3 xsi:type=\"xsd:string\">" + lastName + "</v3>" +
                    "<v4 xsi:type=\"xsd:string\">" + contactEmail + "</v4>" +
                    "<v5 xsi:type=\"xsd:string\">" + contactPhone + "</v5>" +
                    "<v6 xsi:type=\"xsd:string\">" + countryCode + "</v6>" +
                    "<v7 xsi:type=\"xsd:string\">" + captcha + "</v7>" +
                    "<v8 xsi:type=\"xsd:string\">" + captchaKey + "</v8>" +
                    "</CreateAccount>" +
                    "</SOAP-ENV:Body>" +
                    "</SOAP-ENV:Envelope>";

            // set POST body
            HttpEntity entity;
            entity = new StringEntity(body);
            httpPost.setEntity(entity);
            

            HttpClient httpClient = new DefaultHttpClient();
            // Create a response handler
            HttpResponse httpResponse = httpClient.execute(httpPost);
            if(httpResponse.getStatusLine().getStatusCode() == 200) {
                InputStreamReader isr = new InputStreamReader(httpResponse.getEntity().getContent());
                BufferedReader br = new BufferedReader(isr);

                String line = null;
                
                String username = "";
                String password = "";
                while( (line = br.readLine() ) != null ) {
                    if(!TextUtils.isEmpty(line)) {

                        Matcher matcher = soapResultPattern.matcher(line);
                        if(matcher.matches()) {
                            String strValue = matcher.group(1).trim();
                            if(!TextUtils.isEmpty(strValue)) {
                                
                                String[] strValues = strValue.split("\\|");
                                if(strValues.length > 1) {
                                    username = strValues[0];
                                    password = strValues[1];
                                }
                            }
                            break;
                        }
                    }
                }
                
                Log.d(THIS_FILE, "Account created " + username);
                if(TextUtils.isEmpty(username) || TextUtils.isEmpty(password)) {
                    mHander.sendMessage(mHander.obtainMessage(MSG_SAVE_ERROR, "Invalid datas to create the account"));
                    return false;
                }
                
                AccountCreationResult res = new AccountCreationResult(username, password);
                mHander.sendMessage(mHander.obtainMessage(MSG_SAVE_DONE, res));
                return true;
            }else {
                Log.e(THIS_FILE, "Something went wrong while retrieving the captcha webservice ");
            }

        } catch (Exception e) {
            Log.e(THIS_FILE, "Can't create account", e);
        }
        mHander.sendMessage(mHander.obtainMessage(MSG_SAVE_ERROR, "Error while creating the account"));
        
        return false;
    }

    @Override
    public void afterTextChanged(Editable s) {
        canSave();
    }

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        // Nothing to do
    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
        // Nothing to do
    }
    
    
}
