/* Copyright (C) 2010 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.adapter;

import android.content.Context;
import android.content.res.Resources;

import com.android.emailcommon.provider.Policy;
import com.android.exchange.EasSyncService;
import com.android.exchange.ExchangeService;
import com.android.exchange.R;
import com.android.exchange.SecurityPolicyDelegate;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;

/**
 * Parse the result of the Provision command
 *
 * Assuming a successful parse, we store the PolicySet and the policy key
 */
public class ProvisionParser extends Parser {
    private final EasSyncService mService;
    Policy mPolicy = null;
    String mSecuritySyncKey = null;
    boolean mRemoteWipe = false;
    boolean mIsSupportable = true;
    // An array of string resource id's describing policies that are unsupported by the device/app
    String[] mUnsupportedPolicies;
    boolean smimeRequired = false;

    public ProvisionParser(InputStream in, EasSyncService service) throws IOException {
        super(in);
        mService = service;
    }

    public Policy getPolicy() {
        return mPolicy;
    }

    public String getSecuritySyncKey() {
        return mSecuritySyncKey;
    }

    public boolean getRemoteWipe() {
        return mRemoteWipe;
    }

    public boolean hasSupportablePolicySet() {
        return (mPolicy != null) && mIsSupportable;
    }

    public void clearUnsupportedPolicies() {
        mPolicy = SecurityPolicyDelegate.clearUnsupportedPolicies(mService.mContext, mPolicy);
        mIsSupportable = true;
        mUnsupportedPolicies = null;
    }

    public String[] getUnsupportedPolicies() {
        return mUnsupportedPolicies;
    }

    private void setPolicy(Policy policy) {
        policy.normalize();
        mPolicy = policy;
    }

    private void parseProvisionDocWbxml() throws IOException {
        Policy policy = new Policy();
        ArrayList<Integer> unsupportedList = new ArrayList<Integer>();
        boolean passwordEnabled = false;

        while (nextTag(Tags.PROVISION_EAS_PROVISION_DOC) != END) {
            boolean tagIsSupported = true;
            int res = 0;
            switch (tag) {
                case Tags.PROVISION_DEVICE_PASSWORD_ENABLED:
                    if (getValueInt() == 1) {
                        passwordEnabled = true;
                        if (policy.mPasswordMode == Policy.PASSWORD_MODE_NONE) {
                            policy.mPasswordMode = Policy.PASSWORD_MODE_SIMPLE;
                        }
                    }
                    break;
                case Tags.PROVISION_MIN_DEVICE_PASSWORD_LENGTH:
                    policy.mPasswordMinLength = getValueInt();
                    break;
                case Tags.PROVISION_ALPHA_DEVICE_PASSWORD_ENABLED:
                    if (getValueInt() == 1) {
                        policy.mPasswordMode = Policy.PASSWORD_MODE_STRONG;
                    }
                    break;
                case Tags.PROVISION_MAX_INACTIVITY_TIME_DEVICE_LOCK:
                    // EAS gives us seconds, which is, happily, what the PolicySet requires
                    policy.mMaxScreenLockTime = getValueInt();
                    break;
                case Tags.PROVISION_MAX_DEVICE_PASSWORD_FAILED_ATTEMPTS:
                    policy.mPasswordMaxFails = getValueInt();
                    break;
                case Tags.PROVISION_DEVICE_PASSWORD_EXPIRATION:
                    policy.mPasswordExpirationDays = getValueInt();
                    break;
                case Tags.PROVISION_DEVICE_PASSWORD_HISTORY:
                    policy.mPasswordHistory = getValueInt();
                    break;
                case Tags.PROVISION_ALLOW_CAMERA:
                    policy.mDontAllowCamera = (getValueInt() == 0);
                    break;
                case Tags.PROVISION_ALLOW_SIMPLE_DEVICE_PASSWORD:
                    // Ignore this unless there's any MSFT documentation for what this means
                    // Hint: I haven't seen any that's more specific than "simple"
                    getValue();
                    break;
                // The following policies, if false, can't be supported at the moment
                case Tags.PROVISION_ALLOW_STORAGE_CARD:
                case Tags.PROVISION_ALLOW_UNSIGNED_APPLICATIONS:
                case Tags.PROVISION_ALLOW_UNSIGNED_INSTALLATION_PACKAGES:
                case Tags.PROVISION_ALLOW_WIFI:
                case Tags.PROVISION_ALLOW_TEXT_MESSAGING:
                case Tags.PROVISION_ALLOW_POP_IMAP_EMAIL:
                case Tags.PROVISION_ALLOW_IRDA:
                case Tags.PROVISION_ALLOW_HTML_EMAIL:
                case Tags.PROVISION_ALLOW_BROWSER:
                case Tags.PROVISION_ALLOW_CONSUMER_EMAIL:
                case Tags.PROVISION_ALLOW_INTERNET_SHARING:
                    if (getValueInt() == 0) {
                        tagIsSupported = false;
                        switch(tag) {
                            case Tags.PROVISION_ALLOW_STORAGE_CARD:
                                res = R.string.policy_dont_allow_storage_cards;
                                break;
                            case Tags.PROVISION_ALLOW_UNSIGNED_APPLICATIONS:
                                res = R.string.policy_dont_allow_unsigned_apps;
                                break;
                            case Tags.PROVISION_ALLOW_UNSIGNED_INSTALLATION_PACKAGES:
                                res = R.string.policy_dont_allow_unsigned_installers;
                                break;
                            case Tags.PROVISION_ALLOW_WIFI:
                                res = R.string.policy_dont_allow_wifi;
                                break;
                            case Tags.PROVISION_ALLOW_TEXT_MESSAGING:
                                res = R.string.policy_dont_allow_text_messaging;
                                break;
                            case Tags.PROVISION_ALLOW_POP_IMAP_EMAIL:
                                res = R.string.policy_dont_allow_pop_imap;
                                break;
                            case Tags.PROVISION_ALLOW_IRDA:
                                res = R.string.policy_dont_allow_irda;
                                break;
                            case Tags.PROVISION_ALLOW_HTML_EMAIL:
                                res = R.string.policy_dont_allow_html;
                                policy.mDontAllowHtml = true;
                                break;
                            case Tags.PROVISION_ALLOW_BROWSER:
                                res = R.string.policy_dont_allow_browser;
                                break;
                            case Tags.PROVISION_ALLOW_CONSUMER_EMAIL:
                                res = R.string.policy_dont_allow_consumer_email;
                                break;
                            case Tags.PROVISION_ALLOW_INTERNET_SHARING:
                                res = R.string.policy_dont_allow_internet_sharing;
                                break;
                        }
                        if (res > 0) {
                            unsupportedList.add(res);
                        }
                    }
                    break;
                case Tags.PROVISION_ATTACHMENTS_ENABLED:
                    policy.mDontAllowAttachments = getValueInt() != 1;
                    break;
                // Bluetooth: 0 = no bluetooth; 1 = only hands-free; 2 = allowed
                case Tags.PROVISION_ALLOW_BLUETOOTH:
                    if (getValueInt() != 2) {
                        tagIsSupported = false;
                        unsupportedList.add(R.string.policy_bluetooth_restricted);
                    }
                    break;
                // We may now support device (internal) encryption; we'll check this capability
                // below with the call to SecurityPolicy.isSupported()
                case Tags.PROVISION_REQUIRE_DEVICE_ENCRYPTION:
                    if (getValueInt() == 1) {
                        policy.mRequireEncryption = true;
                    }
                    break;
                // Note this policy; we enforce it in ExchangeService
                case Tags.PROVISION_REQUIRE_MANUAL_SYNC_WHEN_ROAMING:
                    policy.mRequireManualSyncWhenRoaming = getValueInt() == 1;
                    break;
                // We are allowed to accept policies, regardless of value of this tag
                // TODO: When we DO support a recovery password, we need to store the value in
                // the account (so we know to utilize it)
                case Tags.PROVISION_PASSWORD_RECOVERY_ENABLED:
                    // Read, but ignore, value
                    policy.mPasswordRecoveryEnabled = getValueInt() == 1;
                    break;
                // The following policies, if true, can't be supported at the moment
                // Note that DEVICE_ENCRYPTION_ENABLED refers to SD card encryption, which we do
                // not yet support.
                case Tags.PROVISION_DEVICE_ENCRYPTION_ENABLED:
                case Tags.PROVISION_REQUIRE_SIGNED_SMIME_MESSAGES:
                case Tags.PROVISION_REQUIRE_ENCRYPTED_SMIME_MESSAGES:
                case Tags.PROVISION_REQUIRE_SIGNED_SMIME_ALGORITHM:
                case Tags.PROVISION_REQUIRE_ENCRYPTION_SMIME_ALGORITHM:
                    if (getValueInt() == 1) {
                        tagIsSupported = false;
                        if (!smimeRequired) {
                            res = R.string.policy_require_smime;
                            unsupportedList.add(R.string.policy_require_smime);
                            smimeRequired = true;
                        }
                    }
                    break;
                case Tags.PROVISION_MAX_ATTACHMENT_SIZE:
                    int max = getValueInt();
                    if (max > 0) {
                        policy.mMaxAttachmentSize = max;
                    }
                    break;
                // Complex characters are supported
                case Tags.PROVISION_MIN_DEVICE_PASSWORD_COMPLEX_CHARS:
                    policy.mPasswordComplexChars = getValueInt();
                    break;
                // The following policies are moot; they allow functionality that we don't support
                case Tags.PROVISION_ALLOW_DESKTOP_SYNC:
                case Tags.PROVISION_ALLOW_SMIME_ENCRYPTION_NEGOTIATION:
                case Tags.PROVISION_ALLOW_SMIME_SOFT_CERTS:
                case Tags.PROVISION_ALLOW_REMOTE_DESKTOP:
                    skipTag();
                    break;
                // We don't handle approved/unapproved application lists
                case Tags.PROVISION_UNAPPROVED_IN_ROM_APPLICATION_LIST:
                case Tags.PROVISION_APPROVED_APPLICATION_LIST:
                    // Parse and throw away the content
                    if (specifiesApplications(tag)) {
                        tagIsSupported = false;
                        if (tag == Tags.PROVISION_UNAPPROVED_IN_ROM_APPLICATION_LIST) {
                            unsupportedList.add(R.string.policy_app_blacklist);
                        } else {
                            unsupportedList.add(R.string.policy_app_whitelist);
                        }
                    }
                    break;
                // NOTE: These policies are enforced by the server; the calendar age maximum can
                // always be accepted, since we don't have a user-settable option. We only reject
                // email age filters at this point.
                case Tags.PROVISION_MAX_CALENDAR_AGE_FILTER:
                case Tags.PROVISION_MAX_EMAIL_AGE_FILTER:
                    max = getValueInt();
                    // 0 indicates no specified filter
                    if (tag == Tags.PROVISION_MAX_CALENDAR_AGE_FILTER) {
                        policy.mMaxCalendarLookback = max;
                    } else {
                        policy.mMaxEmailLookback = max;
                        if (max != 0) {
                            unsupportedList.add(R.string.policy_max_email_age);
                            tagIsSupported = false;
                        }
                    }
                    break;
                // NOTE: These policies are enforced by the server; we can accept them as is, since
                // we don't allow users to set our truncation size manually
                case Tags.PROVISION_MAX_EMAIL_BODY_TRUNCATION_SIZE:
                case Tags.PROVISION_MAX_EMAIL_HTML_BODY_TRUNCATION_SIZE:
                    String value = getValue();
                    // -1 indicates no required truncation
                    if (!value.equals("-1")) {
                        max = Integer.parseInt(value);
                        if (tag == Tags.PROVISION_MAX_EMAIL_BODY_TRUNCATION_SIZE) {
                            policy.mMaxTextTruncationSize = max;
                        } else {
                            policy.mMaxHtmlTruncationSize = max;
                        }
                    }
                    break;
                default:
                    skipTag();
            }

            if (!tagIsSupported) {
                log("Policy not supported: " + tag);
                mIsSupportable = false;
            }
        }

        // Make sure policy settings are valid; password not enabled trumps other password settings
        if (!passwordEnabled) {
            policy.mPasswordMode = Policy.PASSWORD_MODE_NONE;
        }
        setPolicy(policy);

        // We can only determine whether encryption is supported on device by using isSupported here
        if (!SecurityPolicyDelegate.isSupported(mService.mContext, policy)) {
            log("SecurityPolicy reports PolicySet not supported.");
            mIsSupportable = false;
            unsupportedList.add(R.string.policy_require_encryption);
        }

        if (!unsupportedList.isEmpty()) {
            mUnsupportedPolicies = new String[unsupportedList.size()];
            int i = 0;
            Context context = ExchangeService.getContext();
            if (context != null) {
                Resources resources = context.getResources();
                for (int res: unsupportedList) {
                    mUnsupportedPolicies[i++] = resources.getString(res);
                }
            }
        }
    }

    /**
     * Return whether or not either of the application list tags specifies any applications
     * @param endTag the tag whose children we're walking through
     * @return whether any applications were specified (by name or by hash)
     * @throws IOException
     */
    private boolean specifiesApplications(int endTag) throws IOException {
        boolean specifiesApplications = false;
        while (nextTag(endTag) != END) {
            switch (tag) {
                case Tags.PROVISION_APPLICATION_NAME:
                case Tags.PROVISION_HASH:
                    specifiesApplications = true;
                    break;
                default:
                    skipTag();
            }
        }
        return specifiesApplications;
    }

    /*package*/ void parseProvisionDocXml(String doc) throws IOException {
        Policy policy = new Policy();

        try {
            XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
            XmlPullParser parser = factory.newPullParser();
            parser.setInput(new ByteArrayInputStream(doc.getBytes()), "UTF-8");
            int type = parser.getEventType();
            if (type == XmlPullParser.START_DOCUMENT) {
                type = parser.next();
                if (type == XmlPullParser.START_TAG) {
                    String tagName = parser.getName();
                    if (tagName.equals("wap-provisioningdoc")) {
                        parseWapProvisioningDoc(parser, policy);
                    }
                }
            }
        } catch (XmlPullParserException e) {
           throw new IOException();
        }

        setPolicy(policy);
    }

    /**
     * Return true if password is required; otherwise false.
     */
    private boolean parseSecurityPolicy(XmlPullParser parser, Policy policy)
            throws XmlPullParserException, IOException {
        boolean passwordRequired = true;
        while (true) {
            int type = parser.nextTag();
            if (type == XmlPullParser.END_TAG && parser.getName().equals("characteristic")) {
                break;
            } else if (type == XmlPullParser.START_TAG) {
                String tagName = parser.getName();
                if (tagName.equals("parm")) {
                    String name = parser.getAttributeValue(null, "name");
                    if (name.equals("4131")) {
                        String value = parser.getAttributeValue(null, "value");
                        if (value.equals("1")) {
                            passwordRequired = false;
                        }
                    }
                }
            }
        }
        return passwordRequired;
    }

    private void parseCharacteristic(XmlPullParser parser, Policy policy)
            throws XmlPullParserException, IOException {
        boolean enforceInactivityTimer = true;
        while (true) {
            int type = parser.nextTag();
            if (type == XmlPullParser.END_TAG && parser.getName().equals("characteristic")) {
                break;
            } else if (type == XmlPullParser.START_TAG) {
                if (parser.getName().equals("parm")) {
                    String name = parser.getAttributeValue(null, "name");
                    String value = parser.getAttributeValue(null, "value");
                    if (name.equals("AEFrequencyValue")) {
                        if (enforceInactivityTimer) {
                            if (value.equals("0")) {
                                policy.mMaxScreenLockTime = 1;
                            } else {
                                policy.mMaxScreenLockTime = 60*Integer.parseInt(value);
                            }
                        }
                    } else if (name.equals("AEFrequencyType")) {
                        // "0" here means we don't enforce an inactivity timeout
                        if (value.equals("0")) {
                            enforceInactivityTimer = false;
                        }
                    } else if (name.equals("DeviceWipeThreshold")) {
                        policy.mPasswordMaxFails = Integer.parseInt(value);
                    } else if (name.equals("CodewordFrequency")) {
                        // Ignore; has no meaning for us
                    } else if (name.equals("MinimumPasswordLength")) {
                        policy.mPasswordMinLength = Integer.parseInt(value);
                    } else if (name.equals("PasswordComplexity")) {
                        if (value.equals("0")) {
                            policy.mPasswordMode = Policy.PASSWORD_MODE_STRONG;
                        } else {
                            policy.mPasswordMode = Policy.PASSWORD_MODE_SIMPLE;
                        }
                    }
                }
            }
        }
    }

    private void parseRegistry(XmlPullParser parser, Policy policy)
            throws XmlPullParserException, IOException {
      while (true) {
          int type = parser.nextTag();
          if (type == XmlPullParser.END_TAG && parser.getName().equals("characteristic")) {
              break;
          } else if (type == XmlPullParser.START_TAG) {
              String name = parser.getName();
              if (name.equals("characteristic")) {
                  parseCharacteristic(parser, policy);
              }
          }
      }
    }

    private void parseWapProvisioningDoc(XmlPullParser parser, Policy policy)
            throws XmlPullParserException, IOException {
        while (true) {
            int type = parser.nextTag();
            if (type == XmlPullParser.END_TAG && parser.getName().equals("wap-provisioningdoc")) {
                break;
            } else if (type == XmlPullParser.START_TAG) {
                String name = parser.getName();
                if (name.equals("characteristic")) {
                    String atype = parser.getAttributeValue(null, "type");
                    if (atype.equals("SecurityPolicy")) {
                        // If a password isn't required, stop here
                        if (!parseSecurityPolicy(parser, policy)) {
                            return;
                        }
                    } else if (atype.equals("Registry")) {
                        parseRegistry(parser, policy);
                        return;
                    }
                }
            }
        }
    }

    private void parseProvisionData() throws IOException {
        while (nextTag(Tags.PROVISION_DATA) != END) {
            if (tag == Tags.PROVISION_EAS_PROVISION_DOC) {
                parseProvisionDocWbxml();
            } else {
                skipTag();
            }
        }
    }

    private void parsePolicy() throws IOException {
        String policyType = null;
        while (nextTag(Tags.PROVISION_POLICY) != END) {
            switch (tag) {
                case Tags.PROVISION_POLICY_TYPE:
                    policyType = getValue();
                    mService.userLog("Policy type: ", policyType);
                    break;
                case Tags.PROVISION_POLICY_KEY:
                    mSecuritySyncKey = getValue();
                    break;
                case Tags.PROVISION_STATUS:
                    mService.userLog("Policy status: ", getValue());
                    break;
                case Tags.PROVISION_DATA:
                    if (policyType.equalsIgnoreCase(EasSyncService.EAS_2_POLICY_TYPE)) {
                        // Parse the old style XML document
                        parseProvisionDocXml(getValue());
                    } else {
                        // Parse the newer WBXML data
                        parseProvisionData();
                    }
                    break;
                default:
                    skipTag();
            }
        }
    }

    private void parsePolicies() throws IOException {
        while (nextTag(Tags.PROVISION_POLICIES) != END) {
            if (tag == Tags.PROVISION_POLICY) {
                parsePolicy();
            } else {
                skipTag();
            }
        }
    }

    private void parseDeviceInformation() throws IOException {
        while (nextTag(Tags.SETTINGS_DEVICE_INFORMATION) != END) {
            if (tag == Tags.SETTINGS_STATUS) {
                mService.userLog("DeviceInformation status: " + getValue());
            } else {
                skipTag();
            }
        }
    }

    @Override
    public boolean parse() throws IOException {
        boolean res = false;
        if (nextTag(START_DOCUMENT) != Tags.PROVISION_PROVISION) {
            throw new IOException();
        }
        while (nextTag(START_DOCUMENT) != END_DOCUMENT) {
            switch (tag) {
                case Tags.PROVISION_STATUS:
                    int status = getValueInt();
                    mService.userLog("Provision status: ", status);
                    res = (status == 1);
                    break;
                case Tags.SETTINGS_DEVICE_INFORMATION:
                    parseDeviceInformation();
                    break;
                case Tags.PROVISION_POLICIES:
                    parsePolicies();
                    break;
                case Tags.PROVISION_REMOTE_WIPE:
                    // Indicate remote wipe command received
                    mRemoteWipe = true;
                    break;
                default:
                    skipTag();
            }
        }
        return res;
    }
}
