<?xml version="1.0" encoding="UTF-8" ?>
<!--
  Licensed to the Apache Software Foundation (ASF) under one
  or more contributor license agreements.  See the NOTICE file
  distributed with this work for additional information
  regarding copyright ownership.  The ASF licenses this file
  to you under the Apache License, Version 2.0 (the
  "License"); you may not use this file except in compliance
  with the License.  You may obtain a copy of the License at
  
      http://www.apache.org/licenses/LICENSE-2.0
    	  
  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an
  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  KIND, either express or implied.  See the License for the
  specific language governing permissions and limitations
  under the License.
  
-->
<library>

<script>
<![CDATA[

var appletIsLoaded = false;
var returnObject = null

var returnObjectDialer = null

flash.external.ExternalInterface.addCallback("sipStatusMessage", null, sipStatusMessage);
flash.external.ExternalInterface.addCallback("sipLoginSuccess", null, sipLoginSuccess);
flash.external.ExternalInterface.addCallback("sipLoginFail", null, sipLoginFail);


flash.external.ExternalInterface.addCallback("callbackgetAppletStatus", null, callbackgetAppletStatus);
flash.external.ExternalInterface.addCallback("callbackLoginSipUser", null, callbackLoginSipUser);
flash.external.ExternalInterface.addCallback("callbackregister", null, callbackregister);
flash.external.ExternalInterface.addCallback("callbackDTMFButton", null, callbackDTMFButton);
flash.external.ExternalInterface.addCallback("preCustomStartCallByCallToCallBack", null, preCustomStartCallByCallToCallBack);
flash.external.ExternalInterface.addCallback("preCustomStartCallBack", null, preCustomStartCallBack);
flash.external.ExternalInterface.addCallback("startCallCallBack", null, startCallCallBack);


function sipStatusMessage(msg) {
	
	if ($debug) Debug.write("sipStatusMessage :: ",msg);
	
}

function sipLoginSuccess(msg) {
    
    if ($debug) Debug.write("sipLoginSuccess :: ",msg);
    
    returnObject.onSipSuccess.sendEvent();
    
}

function sipLoginFail(msg) {
    
    if ($debug) Debug.write("sipLoginFail :: ",msg);
    
    //In case its an Admin Account we send the success message anyway
    //So that he can check the User-SIP Data or other SIP credentials
    
    if (hib.userobject.level_id >= 2) {
    	new lz.labelerrorPopup(canvas,{errorlabelid:898});
        returnObject.onSipSuccess.sendEvent();
    } else {
    	new lz.labelerrorPopup(canvas,{errorlabelid:899});
    }
    
}

function callbackgetAppletStatus(returnValue) {
                    
    if ($debug) Debug.write("callbackgetAppletStatus ",returnValue);
    
    if (returnValue) {
    	appletIsLoaded = returnValue;
    	if ($debug) Debug.info("SIP Applet is Ready !");
    } else {
    	
    	//new lz.labelerrorPopup(canvas,{errorlabelid:892});
    	if ($debug) Debug.warn("SIP Applet is not Ready");
    }
    
}

function sipIsEnabled(){
	return appletIsLoaded;
}

function getAppletStatus() {
    
    if ($debug) Debug.write("initializeSIPApplet :: flash.external.ExternalInterface (getAppletStatus) ");
    
    flash.external.ExternalInterface.call("getAppletStatus");
    
    //lz.Browser.callJS("getAppletStatus",callbackgetAppletStatus);
    
}

function callbackLoginSipUser(returnValue) {
                    
    if ($debug) Debug.write("callbackLoginSipUser ",returnValue);
    
    registerSIPUser();
    
}

function loginSipUser(userSipData,regObject) {
	
	if ($debug) Debug.write("loginSipUser :: ");
	
	if ($debug) Debug.write("loginSipUser :1: ",userSipData.username);
	if ($debug) Debug.write("loginSipUser :2: ",userSipData.userpass);
	if ($debug) Debug.write("loginSipUser :3: ",userSipData.authId);
	
	returnObject = regObject;
	
	flash.external.ExternalInterface.call("omCustomRegister",userSipData.username,userSipData.userpass,userSipData.authId);
	
    //lz.Browser.callJS("omCustomRegister",callbackLoginSipUser,userSipData.username,userSipData.userpass,userSipData.authId);
	
}

function callbackregister(returnValue) {
                    
    if ($debug) Debug.write("callbackregister ",returnValue);
    
}

function registerSIPUser(userSipData) {
    
    if ($debug) Debug.write("loginSipUser :: ");
    
    flash.external.ExternalInterface.call("register");
    
    //lz.Browser.callJS("register",callbackregister);
    
}


function callDTMFButton(returnObjectDialerRef,number) {
    
    returnObjectDialer = returnObjectDialerRef;
    
    if ($debug) Debug.write("callDTMFButton :1: ",number);
    
    flash.external.ExternalInterface.call("DTMFButton",number);
    
    //lz.Browser.callJS("DTMFButton",callbackDTMFButton,number);
    
}

function callbackDTMFButton(returnValue) {
                    
    if ($debug) Debug.write("callbackDTMFButton ",returnValue);
    
    returnObjectDialer.doNextSipNumber();
    
}

function preCustomStartCallByCallTo(sipNumber) {
	
	//preCustomStartCall(); startCall();
	
	flash.external.ExternalInterface.call("preCustomStartCallByCallTo",sipNumber);
    
    //lz.Browser.callJS("preCustomStartCallByCallTo",preCustomStartCallByCallToCallBack,sipNumber);
    
}

function preCustomStartCallByCallToCallBack(returnValue) {
    
	if ($debug) Debug.write("preCustomStartCallByCallToCallBack ",returnValue);
	
    startCall();
    
}


function preCustomStartCall() {
    
    //preCustomStartCall(); startCall();
    
	flash.external.ExternalInterface.call("preCustomStartCall");
    
    //lz.Browser.callJS("preCustomStartCall",preCustomStartCallBack);
    
}

function preCustomStartCallBack(returnValue) {
    
	if ($debug) Debug.write("preCustomStartCallBack ",returnValue);
	
    //preCustomStartCall(); startCall();
    startCall();
    
}

function startCall() {
    
    //preCustomStartCall(); startCall();
    
	flash.external.ExternalInterface.call("startCall");
    
    //lz.Browser.callJS("startCall",startCallCallBack);
    
}

function startCallCallBack(returnValue) {
    
    if ($debug) Debug.write("startCallCallBack ",returnValue);
    
    returnObjectDialer.ringring();
    
}

]]>
</script>
		
</library>
