/** **************************************************************************
 * Copyright (C) 2017 ecsec GmbH.
 * All rights reserved.
 * Contact: ecsec GmbH (info@ecsec.de)
 *
 * This file is part of the Open eCard App.
 *
 * GNU General Public License Usage
 * This file may be used under the terms of the GNU General Public
 * License version 3.0 as published by the Free Software Foundation
 * and appearing in the file LICENSE.GPL included in the packaging of
 * this file. Please review the following information to ensure the
 * GNU General Public License version 3.0 requirements will be met:
 * http://www.gnu.org/copyleft/gpl.html.
 *
 * Other Usage
 * Alternatively, this file may be used in accordance with the terms
 * and conditions contained in a signed written agreement between
 * you and ecsec GmbH.
 *
 ************************************************************************** */
package org.openecard.android.system;

import android.app.Service;
import android.content.Intent;
import android.os.Build;
import android.os.IBinder;
import android.os.RemoteException;
import javax.annotation.Nullable;
import org.openecard.android.activation.AndroidNfcCapabilities;
import static org.openecard.android.system.ServiceConstants.*;
import static org.openecard.android.system.ServiceResponseStatusCodes.*;
import org.openecard.mobile.ex.ApduExtLengthNotSupported;
import org.openecard.mobile.ex.NfcDisabled;
import org.openecard.mobile.ex.NfcUnavailable;
import org.openecard.mobile.ex.UnableToInitialize;
import org.openecard.mobile.system.OpeneCardContext;
import org.openecard.mobile.system.OpeneCardContextConfig;
import static org.openecard.mobile.system.ServiceMessages.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Implementation of the Android service managing the Open eCard Stack.
 *
 * @author Mike Prechtl
 * @author Tobias Wich
 */
public class OpeneCardServiceImpl extends Service {

    private static final Logger LOG = LoggerFactory.getLogger(OpeneCardServiceInt.class);

    private static OpeneCardContext context;
    private boolean isRequiredAPIUsed = false;

    @Nullable
    public static OpeneCardContext getContext() {
	return context;
    }

    @Override
    public void onCreate() {
	super.onCreate();
	isRequiredAPIUsed = Build.VERSION.SDK_INT >= REQUIRED_API;
    }

    @Override
    public void onDestroy() {
	try {
	    mBinder.stopService();
	} catch (RemoteException ex) {
	    LOG.error("Error stopping Open eCard Service.", ex);
	}
	super.onDestroy();
    }

    @Override
    public IBinder onBind(Intent intent) {
	return mBinder;
    }

    private final OpeneCardService.Stub mBinder = new OpeneCardServiceInt();

    ///
    /// Service Implementation
    ///
    private class OpeneCardServiceInt extends OpeneCardService.Stub {

	@Override
	public ServiceResponse startService() throws RemoteException {
	    if (context == null) {
		LOG.info("Start Open eCard Service...");
		ServiceResponse response;
		try {
		    // build response whether the initialization of app context was successful or failed.
		    if (isRequiredAPIUsed) {
			context = initializeContext();
			response = new ServiceResponse(INIT_SUCCESS, SERVICE_RESPONSE_OK);
		    } else {
			LOG.warn(BELOW_API_LEVEL_21_NOT_SUPPORTED);
			response = new ServiceErrorResponse(NOT_REQUIRED_API_LEVEL, BELOW_API_LEVEL_21_NOT_SUPPORTED);
		    }
		} catch (UnableToInitialize ex) {
		    response = new ServiceErrorResponse(INTERNAL_ERROR, ex.getMessage());
		} catch (NfcDisabled ex) {
		    response = new ServiceWarningResponse(NFC_NOT_ENABLED, ex.getMessage());
		} catch (NfcUnavailable ex) {
		    response = new ServiceErrorResponse(NFC_NOT_AVAILABLE, ex.getMessage());
		} catch (ApduExtLengthNotSupported ex) {
		    response = new ServiceErrorResponse(NFC_NO_EXTENDED_LENGTH, ex.getMessage());
		}
		return response;
	    } else {
		LOG.info("Service already started, nothing to do here.");
		return new ServiceResponse(INIT_SUCCESS, SERVICE_RESPONSE_OK);
	    }
	}

	@Override
	public ServiceResponse stopService() throws RemoteException {
	    if (context != null) {
		LOG.info("Stop Open eCard Service...");
		boolean resultCode = context.shutdown();
		context = null;
		ServiceResponse response = null;
		if (resultCode) {
		    response = new ServiceResponse(SHUTDOWN_SUCCESS, SERVICE_TERMINATE_SUCCESS);
		} else {
		    response = new ServiceWarningResponse(SHUTDOWN_FAILED, SERVICE_TERMINATE_FAILURE);
		}

		stopSelf();
		return response;
	    } else {
		LOG.info("Stop Open eCard Service not necessary.");
		return new ServiceResponse(SHUTDOWN_SUCCESS, SERVICE_TERMINATE_SUCCESS);
	    }
	}

	private OpeneCardContext initializeContext() throws UnableToInitialize, NfcUnavailable, NfcDisabled, ApduExtLengthNotSupported {
	    AndroidNfcCapabilities nfc = AndroidNfcCapabilities.create(getApplicationContext());
	    OpeneCardContext octx = new OpeneCardContext(nfc, new OpeneCardContextConfig("org.openecard.scio.NFCFactory", "org.openecard.ws.android.AndroidMarshaller"));
	    octx.initialize();
	    return octx;
	}
    }
}

@@ -4950,17 +4950,16 @@
 tConfig(
-%22
 org.open
@@ -4969,16 +4969,23 @@
 rd.scio.
+Android
 NFCFacto
@@ -4990,12 +4990,35 @@
 tory
-%22
+.class.getCanonicalName()
 , 
-%22
 org.
@@ -5055,17 +5055,41 @@
 rshaller
-%22
+.class.getCanonicalName()
 ));%0A%09   

Load Context correctly