/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * Licensed 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.
 */

package com.android.exchange.eas;

import android.content.SyncResult;

import com.android.emailcommon.provider.Policy;
import com.android.emailcommon.service.PolicyServiceProxy;
import com.android.exchange.Eas;
import com.android.exchange.EasResponse;
import com.android.exchange.adapter.ProvisionParser;
import com.android.exchange.adapter.Serializer;
import com.android.exchange.adapter.Tags;
import com.android.mail.utils.LogUtils;

import org.apache.http.HttpEntity;

import java.io.IOException;

/**
 * Implements the EAS Provision protocol.
 *
 * Provisioning actually consists of two server interactions:
 * 1) Ask the server for the required policies.
 * 2) Acknowledge our disposition for enforcing those policies.
 *
 * The structure of the requests and response are essentially the same for both, so we use the
 * same code and vary slightly based on which one we're doing. Also, provisioning responses can tell
 * us to wipe the device, so we need to handle that too.
 * TODO: Make it possible to ack separately, possibly by splitting into separate operations.
 * See http://msdn.microsoft.com/en-us/library/ee203567(v=exchg.80).aspx for more details.
 */
public class EasProvision extends EasOperation {

    private static final String LOG_TAG = Eas.LOG_TAG;

    /** The policy type for versions of EAS prior to 2007. */
    public static final String EAS_2_POLICY_TYPE = "MS-WAP-Provisioning-XML";
    /** The policy type for versions of EAS starting with 2007. */
    public static final String EAS_12_POLICY_TYPE = "MS-EAS-Provisioning-WBXML";

    /** The EAS protocol Provision status for "we implement all of the policies" */
    private static final String PROVISION_STATUS_OK = "1";
    /** The EAS protocol Provision status meaning "we partially implement the policies" */
    private static final String PROVISION_STATUS_PARTIAL = "2";

    /** Value for {@link #mPhase} indicating we're performing the initial request. */
    private static final int PHASE_INITIAL = 0;
    /** Value for {@link #mPhase} indicating we're performing the acknowledgement request. */
    private static final int PHASE_ACKNOWLEDGE = 1;
    /** Value for {@link #mPhase} indicating we're performing the acknowledgement for a wipe. */
    private static final int PHASE_WIPE = 2;

    /**
     * This operation doesn't use public result codes because ultimately the operation answers
     * a yes/no question. These result codes are used internally only to communicate from
     * {@link #handleResponse}.
     */

    /** Result code indicating the server's policy can be fully supported. */
    private static final int RESULT_POLICY_SUPPORTED = 1;
    /** Result code indicating the server's policy cannot be fully supported. */
    private static final int RESULT_POLICY_UNSUPPORTED = 2;
    /** Result code indicating the server sent a remote wipe directive. */
    private static final int RESULT_REMOTE_WIPE = 3;

    private Policy mPolicy;
    private String mPolicyKey;
    private String mStatus;

    /**
     * Because this operation supports variants of the request and parsing, and {@link EasOperation}
     * has no way to communicate this into {@link #performOperation}, we use this member variable
     * to vary how {@link #getRequestEntity} and {@link #handleResponse} work.
     */
    private int mPhase;

    public EasProvision(final EasOperation parentOperation) {
        super(parentOperation);
        mPolicy = null;
        mPolicyKey = null;
        mStatus = null;
        mPhase = 0;
    }

    private int performInitialRequest(final SyncResult syncResult) {
        mPhase = PHASE_INITIAL;
        return performOperation(syncResult);
    }

    private void performAckRequestForWipe(final SyncResult syncResult) {
        mPhase = PHASE_WIPE;
        performOperation(syncResult);
    }

    private int performAckRequest(final SyncResult syncResult, final boolean isPartial) {
        mPhase = PHASE_ACKNOWLEDGE;
        mStatus = isPartial ? PROVISION_STATUS_PARTIAL : PROVISION_STATUS_OK;
        return performOperation(syncResult);
    }

    /**
     * Make the provisioning calls to determine if we can handle the required policy.
     * @return The {@link Policy} if we support it, or null otherwise.
     */
    public final Policy test() {
        int result = performInitialRequest(null);
        if (result == RESULT_POLICY_UNSUPPORTED) {
            // Check if the server will permit partial policies.
            result = performAckRequest(null, true);
        }
        if (result == RESULT_POLICY_SUPPORTED) {
            // The server is ok with us not supporting everything, so clear the unsupported ones.
            mPolicy.mProtocolPoliciesUnsupported = null;
        }
        return (result == RESULT_POLICY_SUPPORTED || result == RESULT_POLICY_UNSUPPORTED)
                ? mPolicy : null;
    }

    /**
     * Get the required policy from the server and enforce it.
     * @param syncResult The {@link SyncResult}, if anym for this operation.
     * @param accountId The id for the account for this request.
     * @return Whether we succeeded in provisioning this account.
     */
    public final boolean provision(final SyncResult syncResult, final long accountId) {
        final int result = performInitialRequest(syncResult);

        if (result < 0) {
            return false;
        }

        if (result == RESULT_REMOTE_WIPE) {
            performAckRequestForWipe(syncResult);
            LogUtils.i(LOG_TAG, "Executing remote wipe");
            PolicyServiceProxy.remoteWipe(mContext);
            return false;
        }

        // Apply the policies (that we support) with the temporary key.
        mPolicy.mProtocolPoliciesUnsupported = null;
        PolicyServiceProxy.setAccountPolicy(mContext, accountId, mPolicy, null);
        if (!PolicyServiceProxy.isActive(mContext, mPolicy)) {
            return false;
        }

        // Acknowledge to the server and make sure all's well.
        if (performAckRequest(syncResult, result == RESULT_POLICY_UNSUPPORTED) ==
                RESULT_POLICY_UNSUPPORTED) {
            return false;
        }

        // Write the final policy key to the Account.
        PolicyServiceProxy.setAccountPolicy(mContext, accountId, mPolicy, mPolicyKey);

        // For 12.1 and 14.0, after provisioning we need to also send the device information via
        // the Settings command.
        // See the comments for EasSettings for more details.
        final double version = getProtocolVersion();
        if (version == Eas.SUPPORTED_PROTOCOL_EX2007_SP1_DOUBLE
                || version == Eas.SUPPORTED_PROTOCOL_EX2010_DOUBLE) {
            final EasSettings settingsOperation = new EasSettings(this);
            if (!settingsOperation.sendDeviceInformation(syncResult)) {
                // If the Settings command failed, so do we.
                return false;
            }
        }

        return true;
    }

    @Override
    protected String getCommand() {
        return "Provision";
    }

    @Override
    protected HttpEntity getRequestEntity() throws IOException {
        final Serializer s = new Serializer();
        s.start(Tags.PROVISION_PROVISION);

        // When requesting the policy in 14.1, we also need to send device information.
        if (mPhase == PHASE_INITIAL &&
                getProtocolVersion() >= Eas.SUPPORTED_PROTOCOL_EX2010_SP1_DOUBLE) {
            addDeviceInformationToSerlializer(s);
        }
        s.start(Tags.PROVISION_POLICIES);
        s.start(Tags.PROVISION_POLICY);
        s.data(Tags.PROVISION_POLICY_TYPE, getPolicyType());

        // When acknowledging a policy, we tell the server whether we applied the policy.
        if (mPhase == PHASE_ACKNOWLEDGE) {
            s.data(Tags.PROVISION_POLICY_KEY, mPolicyKey);
            s.data(Tags.PROVISION_STATUS, mStatus);
        }
        if (mPhase == PHASE_WIPE) {
            s.start(Tags.PROVISION_REMOTE_WIPE);
            s.data(Tags.PROVISION_STATUS, PROVISION_STATUS_OK);
            s.end();
        }
        s.end().end().end().done(); // PROVISION_POLICY, PROVISION_POLICIES, PROVISION_PROVISION

        return makeEntity(s);
    }

    @Override
    protected int handleResponse(final EasResponse response, final SyncResult syncResult)
            throws IOException {
        final ProvisionParser pp = new ProvisionParser(mContext, response.getInputStream());
        // If this is the response for a remote wipe ack, it doesn't have anything useful in it.
        // Just go ahead and return now.
        if (mPhase == PHASE_WIPE) {
            return RESULT_REMOTE_WIPE;
        }

        if (!pp.parse()) {
            throw new IOException("Error while parsing response");
        }

        // What we care about in the response depends on what phase we're in.
        if (mPhase == PHASE_INITIAL) {
            if (pp.getRemoteWipe()) {
                return RESULT_REMOTE_WIPE;
            }
            mPolicy = pp.getPolicy();
            mPolicyKey = pp.getSecuritySyncKey();

            return (pp.hasSupportablePolicySet()
                    ? RESULT_POLICY_SUPPORTED : RESULT_POLICY_UNSUPPORTED);
        }

        if (mPhase == PHASE_ACKNOWLEDGE) {
            mPolicyKey = pp.getSecuritySyncKey();
            return (mPolicyKey != null ? RESULT_POLICY_SUPPORTED : RESULT_POLICY_UNSUPPORTED);
        }

        // Note: this should be unreachable, but the compiler doesn't know it.
        // If we somehow get here, act like we can't do anything.
        return RESULT_POLICY_UNSUPPORTED;
    }

    @Override
    protected boolean handleProvisionError(final SyncResult syncResult, final long accountId) {
        // If we get a provisioning error while doing provisioning, we should not recurse.
        return false;
    }

    /**
     * @return The policy type for this connection.
     */
    private final String getPolicyType() {
        return (getProtocolVersion() >= Eas.SUPPORTED_PROTOCOL_EX2007_DOUBLE) ?
                EAS_12_POLICY_TYPE : EAS_2_POLICY_TYPE;
    }
}
