
package mylip;

import org.linphone.core.*;

import org.linphone.core.LinphoneCall.State;
import org.linphone.core.LinphoneCore.AuthMethod;
import org.linphone.core.LinphoneCore.EcCalibratorStatus;
import org.linphone.core.LinphoneCore.GlobalState;
import org.linphone.core.LinphoneCore.LogCollectionUploadState;
import org.linphone.core.LinphoneCore.RegistrationState;
import org.linphone.core.LinphoneCore.RemoteProvisioningState;
import  org.linphone.core.LinphoneCoreFactory;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.util.Timer;
//import java.util.TimerTask;

import android.content.Context;
//import android.content.pm.PackageManager.NameNotFoundException;
//import android.content.res.Resources;
//import android.view.SurfaceView;
//import anywheresoftware.b4a.AbsObjectWrapper;
import anywheresoftware.b4a.BA;
import anywheresoftware.b4a.BA.Author;
import anywheresoftware.b4a.BA.DependsOn;
import anywheresoftware.b4a.BA.Events;
import anywheresoftware.b4a.BA.ShortName;
import anywheresoftware.b4a.BA.Permissions;
import anywheresoftware.b4a.BA.Version;
//import anywheresoftware.b4a.BA.ActivityObject;











@ShortName("MyLip")
@Author("Semendey")
@Permissions(values = { "android.permission.INTERNET", "android.permission.RECORD_AUDIO", "android.permission.ACCESS_NETWORK_STATE","android.permission.FOREGROUND_SERVICE","android.permission.WAKE_LOCK" })
@Version(1.0f)
@DependsOn(values = { "linphone-sdk" })

@Events(values={"CallFinished,StateCallFinishing  "})

//@ActivityObject

public  class MyLipPhone {	

//public  class MyLipPhone  {		
	private BA ba;
	private String event;

    public static MyLipPhone mInstance;
    public LinphoneCore mLinphoneCore;
    public static Context mContext;

		public void initialize(BA ba, String event) {	
		this.ba = ba;
		this.event = event;
		mContext = ba.context;
		BA.Log("1"); 
        LinphoneMiniManager mLinphoneManager = new LinphoneMiniManager(mContext);
        BA.Log("2"); 
        mLinphoneCore = mLinphoneManager.getLc();
        mInstance = this;
        //setObject((LinphoneCore) mLinphoneManager);    	
	}


  class LinphoneMiniManager implements LinphoneCoreListener {

	
			//public LinphoneMiniManager mInstance;
			public Context mContext;
			public LinphoneCore mCore;
			public LinphoneCoreFactory mFactory;
		    //public static LinphonePreferences mPrefs;
			public Timer mTimer;
			//public SurfaceView mCaptureView;
			//public CallbackContext mCallbackContext;
			//public CallbackContext mLoginCallbackContext;
    
			
			public LinphoneMiniManager(Context c) {
				BA.Log("2"); 
				mContext = c;
			
				LinphoneCoreFactory.instance().setDebugMode(true, "Linphone Mini");
		        //mPrefs = LinphonePreferences.instance();

				BA.Log("3"); 
				////////////////////////////////////////////////////////////////////////////////////////
				BA.Log("mCore");
				/*
				try {
					mCore = LinphoneCoreFactory.instance().createLinphoneCore((LinphoneCoreListener) mInstance, mContext);
				} catch (LinphoneCoreException e) {
					// TODO Автоматически созданный блок catch
					e.printStackTrace();
				}
				*/		
				BA.Log("mCore 2");		
						
						
				//mCore = LinphoneCoreFactory.instance().createLinphoneCore(this, basePath + "/.linphonerc", basePath + "/linphonerc", null, mContext);
				

				 

/*
				setUserAgent();
				//setFrontCamAsDefault();
				startIterate();
				mInstance = this;
				mCore.setNetworkReachable(true); // Let's assume it's true

				mCore.addListener((LinphoneCoreListener)mContext);
				mCaptureView = new SurfaceView(mContext);
				
				
				
				
				
							mCore.setContext(mContext);


							int availableCores = Runtime.getRuntime().availableProcessors();
							BA.Log("MediaStreamer : " + availableCores + " cores detected and configured");
							mCore.setCpuCount(availableCores);

							int migrationResult = getLc().migrateToMultiTransport();
							BA.Log( "Migration to multi transport result = " + migrationResult);

							mCore.setNetworkReachable(true);

							// echo cancellation
							boolean isEchoCancellation =  true;
							mCore.enableEchoCancellation(isEchoCancellation);

							// adaptive rate control
							boolean isAdaptiveRateControl = true;
							mCore.enableAdaptiveRateControl(isAdaptiveRateControl);

							// audio bit rate setting
							//LinphoneUtils.getConfig(mServiceContext).setInt("audio", "codec_bitrate_limit", 128);

				    		mCore.setPreferredVideoSizeByName("720p");
				    		mCore.setUploadBandwidth(1536);
				    		mCore.setDownloadBandwidth(1536);

				    		mCore.setVideoPolicy(mCore.getVideoAutoInitiatePolicy(), true);
				    		mCore.setVideoPolicy(true, mCore.getVideoAutoAcceptPolicy());
				    		mCore.enableVideo(true, true);

				    		setCodecMime();
		*/		    		
			}
			
		    public LinphoneCore getLc(){
		        return mCore;
		    }

		    /*
			private void copyAssetsFromPackage(String basePath) throws IOException {
				String package_name = mContext.getPackageName();
				Resources resources = mContext.getResources();

				//copyIfNotExist(mContext, resources.getIdentifier("oldphone_mono", "raw", package_name), basePath + "/oldphone_mono.wav");
				//copyIfNotExist(mContext, resources.getIdentifier("ringback", "raw", package_name), basePath + "/ringback.wav");
				//copyIfNotExist(mContext, resources.getIdentifier("toy_mono", "raw", package_name), basePath + "/toy_mono.wav");
				copyIfNotExist(mContext, resources.getIdentifier("linphonerc_default", "raw", package_name), basePath + "/.linphonerc");
				copyFromPackage(mContext, resources.getIdentifier("linphonerc_factory", "raw", package_name), new File(basePath + "/linphonerc").getName());
				copyIfNotExist(mContext, resources.getIdentifier("lpconfig", "raw", package_name), basePath + "/lpconfig.xsd");
				//copyIfNotExist(mContext, resources.getIdentifier("rootca", "raw", package_name), basePath + "/rootca.pem");
				//copyIfNotExist(mContext, resources.getIdentifier("vcard_grammar", "raw", package_name), basePath + "/vcard_grammar.pem");
				//copyIfNotExist(mContext, resources.getIdentifier("cpim_grammar", "raw", package_name), basePath + "/cpim_grammar.pem");
			}
			*/
			public void copyIfNotExist(Context context, int ressourceId, String target) throws IOException {
				File lFileToCopy = new File(target);
				if (!lFileToCopy.exists()) {
					copyFromPackage(context, ressourceId, lFileToCopy.getName());
				}
			}

			public void copyFromPackage(Context context, int ressourceId, String target) throws IOException {
				FileOutputStream lOutputStream = context.openFileOutput (target, 0);
				InputStream lInputStream = context.getResources().openRawResource(ressourceId);
				int readByte;
				byte[] buff = new byte[8048];
				while (( readByte = lInputStream.read(buff)) != -1) {
					lOutputStream.write(buff,0, readByte);
				}
				lOutputStream.flush();
				lOutputStream.close();
				lInputStream.close();
			}
/*			
			private void setUserAgent() {
				try {
					String versionName = mContext.getPackageManager().getPackageInfo(mContext.getPackageName(), 0).versionName;
					if (versionName == null) {
						versionName = String.valueOf(mContext.getPackageManager().getPackageInfo(mContext.getPackageName(), 0).versionCode);
					}
					mCore.setUserAgent("LinphoneMiniAndroid", versionName);
				} catch (NameNotFoundException e) {
				}
			}
			
			private void startIterate() {
				TimerTask lTask = new TimerTask() {
					@Override
					public void run() {
						mCore.iterate();
					}
				};

				mTimer = new Timer("LinphoneMini scheduler");
				mTimer.schedule(lTask, 0, 20);
			}
			
			

		    private void setCodecMime()
		    {
		        for (final PayloadType pt : mCore.getVideoCodecs())
		        {
		            BA.Log("setCodecMime = " + pt.getMime());
		            if (!pt.getMime().equals("VP8"))
		            {
		                try
		                {
		                	BA.Log("disable codec " + pt.getMime());
		                    mCore.enablePayloadType(pt, false);
		                }
		                catch (LinphoneCoreException e)
		                {
		                	BA.Log(e.toString() );
		                }
		            }
		        }
		    }

*/	
		    
	    
		    @Override
			public void authInfoRequested(LinphoneCore arg0, String arg1, String arg2, String arg3) {
				// TODO Автоматически созданная заглушка метода
				
			}

			@Override
			public void authenticationRequested(LinphoneCore arg0, LinphoneAuthInfo arg1, AuthMethod arg2) {
				// TODO Автоматически созданная заглушка метода
				
			}

			@Override
			public void callEncryptionChanged(LinphoneCore arg0, LinphoneCall arg1, boolean arg2, String arg3) {
				// TODO Автоматически созданная заглушка метода
				
			}

			@Override
			public void callState(LinphoneCore arg0, LinphoneCall arg1, State arg2, String arg3) {
				// TODO Автоматически созданная заглушка метода
				
			}

			@Override
			public void callStatsUpdated(LinphoneCore arg0, LinphoneCall arg1, LinphoneCallStats arg2) {
				// TODO Автоматически созданная заглушка метода
				
			}

			@Override
			public void configuringStatus(LinphoneCore arg0, RemoteProvisioningState arg1, String arg2) {
				// TODO Автоматически созданная заглушка метода
				
			}

			@Override
			public void displayMessage(LinphoneCore arg0, String arg1) {
				// TODO Автоматически созданная заглушка метода
				
			}

			@Override
			public void displayStatus(LinphoneCore arg0, String arg1) {
				// TODO Автоматически созданная заглушка метода
				
			}

			@Override
			public void displayWarning(LinphoneCore arg0, String arg1) {
				// TODO Автоматически созданная заглушка метода
				
			}

			@Override
			public void dtmfReceived(LinphoneCore arg0, LinphoneCall arg1, int arg2) {
				// TODO Автоматически созданная заглушка метода
				
			}

			@Override
			public void ecCalibrationStatus(LinphoneCore arg0, EcCalibratorStatus arg1, int arg2, Object arg3) {
				// TODO Автоматически созданная заглушка метода
				
			}

			@Override
			public void fileTransferProgressIndication(LinphoneCore arg0, LinphoneChatMessage arg1,
					LinphoneContent arg2, int arg3) {
				// TODO Автоматически созданная заглушка метода
				
			}

			@Override
			public void fileTransferRecv(LinphoneCore arg0, LinphoneChatMessage arg1, LinphoneContent arg2, byte[] arg3,
					int arg4) {
				// TODO Автоматически созданная заглушка метода
				
			}

			@Override
			public int fileTransferSend(LinphoneCore arg0, LinphoneChatMessage arg1, LinphoneContent arg2,
					ByteBuffer arg3, int arg4) {
				// TODO Автоматически созданная заглушка метода
				return 0;
			}

			@Override
			public void friendListCreated(LinphoneCore arg0, LinphoneFriendList arg1) {
				// TODO Автоматически созданная заглушка метода
				
			}

			@Override
			public void friendListRemoved(LinphoneCore arg0, LinphoneFriendList arg1) {
				// TODO Автоматически созданная заглушка метода
				
			}

			@Override
			public void globalState(LinphoneCore arg0, GlobalState arg1, String arg2) {
				// TODO Автоматически созданная заглушка метода
				
			}

			@Override
			public void infoReceived(LinphoneCore arg0, LinphoneCall arg1, LinphoneInfoMessage arg2) {
				// TODO Автоматически созданная заглушка метода
				
			}

			@Override
			public void isComposingReceived(LinphoneCore arg0, LinphoneChatRoom arg1) {
				// TODO Автоматически созданная заглушка метода
				
			}

			@Override
			public void messageReceived(LinphoneCore arg0, LinphoneChatRoom arg1, LinphoneChatMessage arg2) {
				// TODO Автоматически созданная заглушка метода
				
			}

			@Override
			public void messageReceivedUnableToDecrypted(LinphoneCore arg0, LinphoneChatRoom arg1,
					LinphoneChatMessage arg2) {
				// TODO Автоматически созданная заглушка метода
				
			}

			@Override
			public void networkReachableChanged(LinphoneCore arg0, boolean arg1) {
				// TODO Автоматически созданная заглушка метода
				
			}

			@Override
			public void newSubscriptionRequest(LinphoneCore arg0, LinphoneFriend arg1, String arg2) {
				// TODO Автоматически созданная заглушка метода
				
			}

			@Override
			public void notifyPresenceReceived(LinphoneCore arg0, LinphoneFriend arg1) {
				// TODO Автоматически созданная заглушка метода
				
			}

			@Override
			public void notifyReceived(LinphoneCore arg0, LinphoneCall arg1, LinphoneAddress arg2, byte[] arg3) {
				// TODO Автоматически созданная заглушка метода
				
			}

			@Override
			public void notifyReceived(LinphoneCore arg0, LinphoneEvent arg1, String arg2, LinphoneContent arg3) {
				// TODO Автоматически созданная заглушка метода
				
			}

			@Override
			public void publishStateChanged(LinphoneCore arg0, LinphoneEvent arg1, PublishState arg2) {
				// TODO Автоматически созданная заглушка метода
				
			}

			@Override
			public void registrationState(LinphoneCore arg0, LinphoneProxyConfig arg1, RegistrationState arg2,
					String arg3) {
				// TODO Автоматически созданная заглушка метода
				raiseEvent("registrationState");	
			}

			@Override
			public void show(LinphoneCore arg0) {
				// TODO Автоматически созданная заглушка метода
				
			}

			@Override
			public void subscriptionStateChanged(LinphoneCore arg0, LinphoneEvent arg1, SubscriptionState arg2) {
				// TODO Автоматически созданная заглушка метода
				
			}

			@Override
			public void transferState(LinphoneCore arg0, LinphoneCall arg1, State arg2) {
				// TODO Автоматически созданная заглушка метода
				
			}

			@Override
			public void uploadProgressIndication(LinphoneCore arg0, int arg1, int arg2) {
				// TODO Автоматически созданная заглушка метода
				
			}

			@Override
			public void uploadStateChanged(LinphoneCore arg0, LogCollectionUploadState arg1, String arg2) {
				// TODO Автоматически созданная заглушка метода
				
			}
			
			
			
	    	private void raiseEvent(String baseEvent) {
	    		String eventName = event.concat("_").concat(baseEvent).toLowerCase(BA.cul);
	    		if (ba.subExists(eventName)) {
	    			BA.Log(eventName);
	    			//ba.raiseEvent(getObject(), eventName);
	    			ba.raiseEvent(mInstance, eventName);
	    			//ba.raiseEvent(this, eventName);		 
	    		}
	    	}
			
/////////////////////////////////////////////////////////////////////////////////////	    
}




}




//Сначала необходимо открыть сервис, после чего будет завершена операция регистрации, и вы сможете совершать звонки.
/*

// Register VoIP
    public void registerVoip(String sipAccount) {
        if (LinphoneService.isReady()) {// determine whether to open service
            registerCall(sipAccount);
        } else {
            mServiceWaitThread = new ServiceWaitThread();
            mServiceWaitThread.start();
        }
    }
    private ServiceWaitThread mServiceWaitThread;
    private class ServiceWaitThread extends Thread {
        @Override
        public void run() {
            super.run();
            while (!LinphoneService.isReady()) {
                try {
                    startService(new Intent(Intent.ACTION_MAIN).setClass(getApplicationContext(), LinphoneService.class));
                    sleep(100);
                } catch (InterruptedException e) {
                    throw new RuntimeException("waiting thread sleep() has been interrupted");
                }
            }
            EventBus.getDefault().postSticky(new LinphoneServiceStartEvent());
            mServiceWaitThread = null;
        }
    }
    // Register VoIP
    public void registerCall(String sipAccount) {
        try {
            PhoneVoiceUtils.getInstance().registerUserAuth(sipAccount, AppString.SIPPASSWORD, AppString.SIPSERVER);
        } catch (LinphoneCoreException e) {
            e.printStackTrace();
        }
    }
    
*/




//После успешной регистрации вы можете напрямую вызвать функцию. PhoneVoiceUtils напрямую вызывает функцию

/*
PhoneVoiceUtils.getInstance().startSingleCallingTo(number);
*/

//Добавьте прослушивание вызова, соответствующую операцию в разных состояниях


/*
LinphoneService.addCallback(new PhoneServiceCallback() {
            @Override
            public void callConnected() {
                // call is connected
            }

            @Override
            public void callStart() {
                //establish connection
            }

            @Override
            public void callReleased() {
                // hang up the phone
            }
        });
 */



//повесьте трубку
/*
PhoneVoiceUtils.getInstance().hangUp();
*/

