package org.wso2.carbon.device.mgt.ios.payload.operation;

import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.ios.payload.beans.Email;
import org.wso2.carbon.device.mgt.ios.payload.beans.PayloadOperation;
import org.wso2.carbon.device.mgt.ios.payload.dto.PayloadOperationWrapper;
import org.wso2.carbon.device.mgt.ios.payload.dto.PayloadProperties;
import org.wso2.carbon.device.mgt.ios.payload.exception.PListException;
import org.wso2.carbon.device.mgt.ios.payload.exception.ProfileConfigurationException;
import org.wso2.carbon.device.mgt.ios.payload.util.OperationUtils;
import org.wso2.carbon.user.api.UserStoreException;
import org.wso2.carbon.user.core.service.RealmService;
import org.wso2.carbon.user.api.UserRealm;
import org.wso2.carbon.utils.multitenancy.MultitenantConstants;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class EmailOperations {

    private static final String PAYLOAD_DISPLAY_NAME = "Email Configurations";
    private static final String PAYLOAD_DESCRIPTION = "Email Configurations for %s";
    private static final String EMAIL_ACCOUNT_DESCRIPTION = "EmailAccountDescription";
    private static final String EMAIL_ACCOUNT_NAME = "EmailAccountName";
    private static final String EMAIL_ACCOUNT_TYPE = "EmailAccountType";
    private static final String EMAIL_ADDRESS = "EmailAddress";
    private static final String INCOMING_MAIL_SERVER_AUTHENTICATION = "IncomingMailServerAuthentication";
    private static final String INCOMING_MAIL_SERVER_HOST_NAME = "IncomingMailServerHostName";
    private static final String INCOMING_MAIL_SERVER_PORT_NUMBER = "IncomingMailServerPortNumber";
    private static final String INCOMING_MAIL_SERVER_USE_SSL = "IncomingMailServerUseSSL";
    private static final String INCOMING_MAIL_SERVER_USERNAME = "IncomingMailServerUsername";
    private static final String INCOMING_PASSWORD = "IncomingPassword";
    private static final String OUTGOING_PASSWORD = "OutgoingPassword";
    private static final String OUTGOING_PASSWORD_SAME_AS_INCOMING_PASSWORD = "OutgoingPasswordSameAsIncomingPassword";
    private static final String OUTGOING_MAIL_SERVER_AUTHENTICATION = "OutgoingMailServerAuthentication";
    private static final String OUTGOING_MAIL_SERVER_HOSTNAME = "OutgoingMailServerHostName";
    private static final String OUTGOING_MAIL_SERVER_PORT_NUMBER = "OutgoingMailServerPortNumber";
    private static final String OUTGOING_MAIL_SERVER_USE_SSL = "OutgoingMailServerUseSSL";
    private static final String OUTGOING_MAIL_SERVER_USERNAME = "OutgoingMailServerUsername";
    private static final String PREVENT_MOVE = "PreventMove";
    private static final String PREVENT_APP_SHEET = "PreventAppSheet";
    private static final String SMIME_ENABLED = "SMIMEEnabled";
    private static final String SMIME_SIGNING_CERTIFICATE_UUID = "SMIMESigningCertificateUUID";
    private static final String SMIME_ENCRYPTION_CERTIFICATE_UUID = "SMIMEEncryptionCertificateUUID";
    private static final String SMIME_ENABLE_PER_MESSAGE_SWITCH = "SMIMEEnablePerMessageSwitch";
    private static final String DISABLE_MAIL_RECENTS_SYNCING = "disableMailRecentsSyncing";
    private static final String INCOMING_MAIL_SERVER_IMAP_PATH_PREFIX = "IncomingMailServerIMAPPathPrefix";

    public PayloadOperationWrapper createEmailPayload(Email email) throws PListException,
            ProfileConfigurationException {

        PayloadProperties payloadProperties = generateCommonElements(email,
                OperationUtils.getTenantNameFromOperationID(), OperationUtils.isPayloadRemoveDisallowedForTenant());
        String emailAddress = null;

        email.validateRequest();

        Map<String, Object> commandMap = email.getCommandMap();
        commandMap.put(EMAIL_ACCOUNT_DESCRIPTION, email.getEmailAccountDescription());
        try {
            UserRealm userRealm = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUserRealm();
            if (userRealm != null) {
                emailAddress =  userRealm.getUserStoreManager().getUserClaimValue(PrivilegedCarbonContext.
                                getThreadLocalCarbonContext().getUsername(),"http://wso2.org/claims/emailaddress",
                        "default");
                commandMap.put(EMAIL_ADDRESS, emailAddress);
            }
        } catch (UserStoreException e) {
            throw new PListException("Error occurred while getting the tenant domain.", e);
        }
        if(email.getEmailAccountName() != null && !email.getEmailAccountName().isEmpty()) {
            commandMap.put(EMAIL_ACCOUNT_NAME, email.getEmailAccountName());
        }
        commandMap.put(EMAIL_ACCOUNT_TYPE, email.getEmailAccountType().toString());
        if(email.getEmailAddress() != null && !email.getEmailAddress().isEmpty()) {
            commandMap.put(EMAIL_ADDRESS, email.getEmailAddress());
        } else {
            commandMap.put(EMAIL_ADDRESS, emailAddress);
        }
        commandMap.put(INCOMING_MAIL_SERVER_AUTHENTICATION, email.getIncomingMailServerAuthentication().toString());
        commandMap.put(INCOMING_MAIL_SERVER_HOST_NAME, email.getIncomingMailServerHostName());
        commandMap.put(INCOMING_MAIL_SERVER_PORT_NUMBER, email.getIncomingMailServerPortNumber());
        commandMap.put(INCOMING_MAIL_SERVER_USE_SSL, email.getIncomingMailServerUseSSL());
        if(email.getIncomingMailServerUsername() != null && !email.getIncomingMailServerUsername().isEmpty()) {
            commandMap.put(INCOMING_MAIL_SERVER_USERNAME, email.getIncomingMailServerUsername());
        } else {
            commandMap.put(INCOMING_MAIL_SERVER_USERNAME, emailAddress);
        }
        commandMap.put(INCOMING_PASSWORD, email.getIncomingPassword());
        commandMap.put(OUTGOING_PASSWORD, email.getOutgoingPassword());
        commandMap.put(OUTGOING_PASSWORD_SAME_AS_INCOMING_PASSWORD, email.getOutgoingPasswordSameAsIncomingPassword());
        commandMap.put(OUTGOING_MAIL_SERVER_AUTHENTICATION, email.getOutgoingMailServerAuthentication().toString());
        commandMap.put(OUTGOING_MAIL_SERVER_HOSTNAME, email.getOutgoingMailServerHostName());
        commandMap.put(OUTGOING_MAIL_SERVER_PORT_NUMBER, email.getOutgoingMailServerPortNumber());
        commandMap.put(OUTGOING_MAIL_SERVER_USE_SSL, email.getOutgoingMailServerUseSSL());
        if(email.getOutgoingMailServerUsername() != null && !email.getOutgoingMailServerUsername().isEmpty()) {
            commandMap.put(OUTGOING_MAIL_SERVER_USERNAME, email.getOutgoingMailServerUsername());
        } else {
            commandMap.put(OUTGOING_MAIL_SERVER_USERNAME, emailAddress);
        }
        commandMap.put(PREVENT_MOVE, email.getPreventMove());
        commandMap.put(PREVENT_APP_SHEET, email.getPreventAppSheet());
        commandMap.put(SMIME_ENABLED, email.getSMIMEEnabled());
        commandMap.put(SMIME_SIGNING_CERTIFICATE_UUID, email.getSMIMESigningCertificateUUID());
        commandMap.put(SMIME_ENCRYPTION_CERTIFICATE_UUID, email.getSMIMEEncryptionCertificateUUID());
        commandMap.put(SMIME_ENABLE_PER_MESSAGE_SWITCH, email.getSMIMEEnablePerMessageSwitch());
        commandMap.put(DISABLE_MAIL_RECENTS_SYNCING, email.getDisableMailRecentsSyncing());
        commandMap.put(INCOMING_MAIL_SERVER_IMAP_PATH_PREFIX, email.getIncomingMailServerIMAPPathPrefix());

        List<Object> payloadContent = new ArrayList<Object>();
        payloadContent.add(commandMap);

        PayloadOperationWrapper payloadOperationWrapper = new PayloadOperationWrapper();
        payloadOperationWrapper.setPayload(payloadContent);
        payloadOperationWrapper.setPayloadProperties(payloadProperties);
        return payloadOperationWrapper;
    }

    private PayloadProperties generateCommonElements(Email email, String tenantName,
                                        boolean payloadRemoveDisallowed) {

        PayloadProperties payloadProperties = new PayloadProperties();
        payloadProperties.setTenantName(tenantName);
        payloadProperties.setPayloadType(PayloadOperation.PayloadType.EMAIL.getPayloadType());
        payloadProperties.setPayloadIdentifier(email.getUUID());
        payloadProperties.setPayloadDisplayName(PAYLOAD_DISPLAY_NAME);
        payloadProperties.setPayloadDescription(String.format(PAYLOAD_DESCRIPTION, tenantName));
        payloadProperties.setPayloadRemoveDisallowed(payloadRemoveDisallowed);

        email.populateCommandPayloadElements(payloadProperties);

        return payloadProperties;
    }
}
