package org.obd_dialer;

import java.util.Map;
import java.util.Map.Entry;
import java.sql.Connection;
import java.sql.SQLException;

import org.GenerateCID;
import org.Obd_callflow.Obd_callflow;
import org.feedback.Feedback;
import org.freeswitch.esl.client.IEslEventListener;
import org.freeswitch.esl.client.inbound.Client;
import org.freeswitch.esl.client.transport.event.EslEvent;
import org.freeswitch.esl.client.transport.message.EslHeaders;
import org.freeswitch.esl.client.transport.message.EslMessage;
import org.freeswitch.swig.JavaSession;

public class ExecutorProcess implements Runnable, IEslEventListener {
	public Client client;
	private EslMessage response;
	private OutboundData obd;
	private int duration;
	private String error_code;
	private String status;
	private String failure_point;
	private int final_status;
	private String base_dir;
	JavaSession session = null;
	private String threadStatus;
	private ConnectDB ccDB; 
	private String uuid;
	private static int firstCounter = 0;
	private static int secondCounter = 0;
	
	public ExecutorProcess(String base_dir, Client client, ConnectDB ccDB){
		this.base_dir = base_dir;
		this.client = client;
		this.ccDB = ccDB;
	}

	public void callStatus() {
		GenerateCID genInsertCallStatus = new GenerateCID();
		genInsertCallStatus.insertCallStatus(obd.getCID(),
				obd.getCalltype(),
				obd.getCp_obd_id(),
				obd.getEsmeaddr(),
				obd.getSource_num(),
				obd.getDest_num(),
				obd.getSource_num(),
				obd.getDest_num(),
				status,
				failure_point,
				Integer.parseInt(error_code),
				0,  
				duration, 
				0,  
				obd.getDest_retrials(),
				obd.getFlow_id(), 
				"",  
				0,  
				final_status, 
				obd.getSubmit_time().substring(0, 10),
				obd.getSubmit_time(), 
				obd.getMsg(), 
				0,  
				"",  
				"",
				obd.getFile_id(),
				obd.getMessage_tag(),
				0,
				obd.getDlr(),
				"",
				"",
				"",
		"");
	}

	public void setCallStatus(String uuid) {
		client.sendAsyncApiCommand("uuid_setvar_multi",uuid + " cp_obd_id=" + obd.getCp_obd_id() +
				";dest_retrials=" + obd.getDest_retrials() +
				";submit_time=" + obd.getSubmit_time() +
				";msg=" + obd.getMsg() +
				";file_id=" + obd.getFile_id() +
				";message_tag=" + obd.getMessage_tag() +
				";dlr=" + obd.getDlr() );							
	}

	@Override
	public void eventReceived(EslEvent event) {
		System.out.println("Event is " + event.getEventName() + " Thread name " + Thread.currentThread().getName());
		Map<String, String> header = event.getEventHeaders();
		EslMessage response;
		if(event.getEventName() != null && event.getEventName().contentEquals("CHANNEL_STATE") && header.get("Unique-ID") != null && header.get("Unique-ID").contains(uuid)  ) {
			String call_status = header.get("Answer-State");
			if(call_status != null && call_status.contains("answered")) {
				response = client.sendSyncApiCommand("uuid_getvar",uuid + " answered_time");
				String strAnswer_time = response.getBodyLines().toString();
				System.out.println("Answer Time ... " + strAnswer_time);
				System.out.println("Call has answered...");
				System.out.println("File Playing ...");
				if (obd.getLANGUAGE() != null && !obd.getLANGUAGE().isEmpty()) {
					System.out.println("Playing File with Language - " + base_dir + obd.getMsg_folder() + obd.getLANGUAGE() + "/" + obd.getLANGUAGE() + "_" + obd.getMsg());
					response = client.sendSyncApiCommand("uuid_broadcast", uuid + " playback::'" + base_dir + obd.getMsg_folder() + obd.getLANGUAGE() + "/" + obd.getLANGUAGE() + "_" + obd.getMsg() + "'");
				} else {
					System.out.println("Playing File in Default Language - " + base_dir + obd.getMsg_folder() + obd.getMsg());
					response = client.sendSyncApiCommand("uuid_broadcast", uuid + " playback::'" + base_dir + obd.getMsg_folder() + obd.getMsg() + "'");
				}	
			}
		} else if(event.getEventName() != null && event.getEventName().contentEquals("CHANNEL_EXECUTE_COMPLETE") && header.get("Unique-ID") != null && header.get("Unique-ID").contains(uuid) ) {
			String call_status = header.get("Application-Response");
			if(call_status.contains("FILE PLAYED")) {
				System.out.println("File Playing Done...");
				if ( obd.getFlow_type().toUpperCase().contains("FB") ) {
					client.sendAsyncApiCommand("uuid_setvar", uuid + " feedback_id " + obd.getFlow_id() );
					setCallStatus(uuid);
					//Feedback feedback_thread = new Feedback(uuid, obd.getFlow_id(), obd.getCID(), obd.getEsmeaddr(), obd.getCalltype(), obd.getDest_num(), obd.getLANGUAGE(), base_dir, this);	
					//Thread feed = new Thread(feedback_thread);
					//feed.start();
					return;
				} else if ( obd.getFlow_type().toUpperCase().contains("CF") ) {
					setCallStatus(uuid);									
					Obd_callflow obd_callflow = new Obd_callflow(uuid, obd.getFlow_id(), obd.getCID(), obd.getCalltype(), obd.getDest_num(), obd.getLANGUAGE(), base_dir, obd.getSource_num(), obd.getFile_id(), obd.getMessage_tag(), client, this);	
					Thread obd_cf = new Thread(obd_callflow);
					obd_cf.start();
					client.addEventListener(obd_callflow);
					return;
				} else {
					client.sendAsyncApiCommand("uuid_kill", uuid);
				}
			}
		} else if (event.getEventName() != null && event.getEventName().contentEquals("CHANNEL_HANGUP") && header.get("Unique-ID") != null && header.get("Unique-ID").contains(uuid)) {
			System.out.println("Reset Thread .... " + event.getEventName());
		} else if (event.getEventName() != null && event.getEventName().contentEquals("CHANNEL_HANGUP_COMPLETE") && header.get("Unique-ID") != null && header.get("Unique-ID").contains(uuid)) {
			duration = Integer.parseInt(header.get("variable_billsec").toString());
			error_code = header.get("variable_hangup_cause_q850");
			System.out.println("bill seconds .... " + duration + " error_code ...  " + error_code);
			callStatus();
		}
		
		try {
			event.wait(15000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
	}
	
	@Override
	public void backgroundJobResultReceived(EslEvent event) {
		System.out.println("backgroundJobResultReceived is " + event.getEventName() + " Thread name " + Thread.currentThread().getName());
		System.out.println("firstCounter   " + firstCounter);
		System.out.println("secondCounter  " + secondCounter);
		System.out.println("Number " + obd.getDest_num());
		System.out.println("UUID - " + uuid);
		Map<String, String> header = event.getEventHeaders();
		System.out.println("Job-UUID - " + header.get("Job-UUID"));
		if(header != null && header.get("Job-UUID").contains(uuid)){
			//String call_result = response.getHeaderValue(EslHeaders.Name.REPLY_TEXT);
			String call_result = event.getEventBodyLines().toString();
			System.out.println("Result of Call " + call_result);
			if (call_result.contains("+OK")){										
				ccDB.deleteDB(obd.getUniq_id());
				status = "SUCCESS";
				failure_point = "";
				final_status = 1;
				client.sendAsyncApiCommand("uuid_setvar", uuid + " final_status " + 1 );
				secondCounter ++;
				System.out.println(status);
			}else{
				status = "FAILED";
				failure_point = "Destination";
				System.out.println(status);				
				if (obd.getRetrial_Attempt() >= obd.getRetrial()){
					final_status = 1;
					ccDB.deleteDB(obd.getUniq_id());
				}else{
					final_status = 0;
					System.out.println("Pushing into Retrial Queue");
					ccDB.updateDB(obd.getUniq_id(),obd.getSource_retrials(),(obd.getDest_retrials() + 1),obd.getRetrial_Attempt());						
				}
			}
		} 
		
		try {
			event.wait(15000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
	}
	
	public void run() {
		
		try {
			ConnectDB ccDB = new ConnectDB();
			System.out.println(obd.getUniq_id());				
			if (obd.getDest_num().length() == 12 && obd.getDest_num().substring(0, 2).contains("91")){
				String destFormat = "0" + obd.getDest_num().substring(2,obd.getDest_num().length());
				obd.setDest_num(destFormat);
				System.out.println("Number " + destFormat);
			} else if(obd.getDest_num().length() == 10) {
				String destFormat = "0" + obd.getDest_num();
				obd.setDest_num(destFormat);
				System.out.println("Number " + destFormat);
			}			

			String userData = "UserData=" + obd.getCp_obd_id_desc() + ",AppIdName=" + obd.getCp_obd_id_desc() + ",CallId=" + obd.getUniq_id() + ",CallType=2,RetrialFlag=" + obd.getRetrial_Attempt() + ",esmeaddr=" + obd.getEsmeaddr(); 

			GenerateCID create_uuid = new GenerateCID();
			
			uuid = create_uuid.getUuid(client);
			
			if (uuid != null)
			{
				
				//String command = "{" + userData + ",ignore_early_media=true,origination_uuid=" + uuid + ",originate_timeout=" + obd.getTimeout() + "}freetdm/" + obd.getRoute_id() + "/a/" + obd.getDest_num() + " &playback(" + obd.getMsg_folder() + obd.getMsg() + ")";
				String command = "{" + userData + ",ignore_early_media=true,origination_uuid=" + uuid + ",originate_timeout=" + obd.getTimeout() + ",origination_caller_id_number=" + obd.getCaller_id() + "}freetdm/" + obd.getRoute_id() + "/a/" + obd.getDest_num() + " &park";					
				response = client.sendSyncApiCommand("originate",command);
				firstCounter++;

			} else{
				System.out.println("Failed to Created UUID..");
				ccDB.updateDB(obd.getUniq_id());
			}
		} catch (Throwable e) {
			e.printStackTrace();
		}
		setThreadStatus("IDLE");
	}

	public String getThreadStatus() {
		return threadStatus;
	}

	public void setThreadStatus(String threadStatus) {
		this.threadStatus = threadStatus;
	}

	public OutboundData getObd() {
		return obd;
	}

	public void setObd(OutboundData obd) {
		this.obd = obd;
	}



}
