package org.wso2.carbon.device.mgt.ios.core.service;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
import org.wso2.carbon.device.mgt.common.DeviceManagementException;
import org.wso2.carbon.device.mgt.ios.core.exception.IOSEnrollmentException;
import org.wso2.carbon.device.mgt.ios.core.impl.PKCSSigner;
import org.wso2.carbon.device.mgt.ios.core.impl.RequestHandler;
import org.wso2.carbon.device.mgt.ios.core.internal.IOSEnrollmentServiceHolder;
import org.wso2.carbon.device.mgt.ios.core.util.AppConfigurations;
import org.wso2.carbon.device.mgt.ios.payload.dto.APNSStatus;
import org.wso2.carbon.device.mgt.ios.payload.dto.CertificateAttributes;
import org.wso2.carbon.device.mgt.ios.payload.dto.CheckInMessageType;
import org.wso2.carbon.device.mgt.ios.payload.enrollment.EnrollmentPayloadGenerator;
import org.wso2.carbon.device.mgt.ios.payload.enrollment.EnrollmentAttributeExtractor;
import org.wso2.carbon.device.mgt.ios.payload.exception.PListException;

import java.io.InputStream;
import java.security.cert.X509Certificate;

public class IOSEnrollmentService {

    private static final Log log = LogFactory.getLog(IOSEnrollmentService.class);
	private static IOSEnrollmentService enrollmentService;

    private IOSEnrollmentService() {}

	public static IOSEnrollmentService getInstance() {

		if (enrollmentService == null) {
			enrollmentService = new IOSEnrollmentService();
		}
		return enrollmentService;
	}

	public String generateMobileConfigurations(String challengeToken, String tenantName) throws IOSEnrollmentException {

        EnrollmentPayloadGenerator enrollmentPayloadGenerator = new EnrollmentPayloadGenerator();
        try {
            return enrollmentPayloadGenerator.generateMobileConfigurations(challengeToken,
                tenantName, AppConfigurations.getConfigEntry(AppConfigurations.PROFILE_URL));
        } catch (PListException e) {
            String errorMsg = "Error in generating mobile configurations";
            log.error(errorMsg, e);
            throw new IOSEnrollmentException(errorMsg, e);
        }
    }

    public byte[] handleProfileRequest(InputStream inputStream, String tenant, String topicId,
            CertificateAttributes certAttributes) throws IOSEnrollmentException {

        RequestHandler requestHandler = new RequestHandler();
        return requestHandler.handleProfileRequest(inputStream, tenant, topicId, certAttributes);
    }

    public String extractChallengeTokenFromProfile(InputStream inputStream) throws PListException {
        RequestHandler requestHandler = new RequestHandler();
        return requestHandler.getChallengeTokenFromProfile(inputStream);
    }

    public String extractDeviceIdentifierFromProfile(InputStream inputStream) throws PListException {
        RequestHandler requestHandler = new RequestHandler();
        return requestHandler.getDeviceIdentifierFromProfile(inputStream);
    }

	public CheckInMessageType extractTokens(String xmlProperties) throws PListException {
		EnrollmentAttributeExtractor enrollmentAttributeExtractor = new EnrollmentAttributeExtractor();
		return enrollmentAttributeExtractor.extractTokens(xmlProperties);
	}

	public APNSStatus extractAPNSResponse(String xmlProperties) throws PListException {
		EnrollmentAttributeExtractor enrollmentAttributeExtractor = new EnrollmentAttributeExtractor();
		return enrollmentAttributeExtractor.extractAPNSResponse(xmlProperties);
	}

	public byte[] getSignedData(byte[] input) throws IOSEnrollmentException {
		PKCSSigner pkcsSigner = new PKCSSigner();
		return pkcsSigner.getSignedData(input);
	}

    public byte[] getEncryptedData(byte[] input, X509Certificate certificate) throws IOSEnrollmentException {
        PKCSSigner pkcsSigner = new PKCSSigner();
        return pkcsSigner.getEncryptedData(input, certificate);
    }

    public boolean isEnrolled(DeviceIdentifier deviceIdentifier) throws IOSEnrollmentException {
        try {
            return IOSEnrollmentServiceHolder.getInstance().getDeviceManagementService().isEnrolled(deviceIdentifier);
        } catch (DeviceManagementException e) {
            String errorMsg = "Error in generating mobile configurations";
            log.error(errorMsg);
            throw new IOSEnrollmentException(errorMsg, e);
        }
    }
}
