/*
 * Copyright (C) 2015 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 android.hardware.usb;

import static android.hardware.usb.UsbPortStatus.CONTAMINANT_DETECTION_DETECTED;
import static android.hardware.usb.UsbPortStatus.CONTAMINANT_DETECTION_DISABLED;
import static android.hardware.usb.UsbPortStatus.CONTAMINANT_DETECTION_NOT_DETECTED;
import static android.hardware.usb.UsbPortStatus.CONTAMINANT_DETECTION_NOT_SUPPORTED;
import static android.hardware.usb.UsbPortStatus.DATA_ROLE_DEVICE;
import static android.hardware.usb.UsbPortStatus.DATA_ROLE_HOST;
import static android.hardware.usb.UsbPortStatus.DATA_ROLE_NONE;
import static android.hardware.usb.UsbPortStatus.MODE_AUDIO_ACCESSORY;
import static android.hardware.usb.UsbPortStatus.MODE_DEBUG_ACCESSORY;
import static android.hardware.usb.UsbPortStatus.MODE_DFP;
import static android.hardware.usb.UsbPortStatus.MODE_DUAL;
import static android.hardware.usb.UsbPortStatus.MODE_NONE;
import static android.hardware.usb.UsbPortStatus.MODE_UFP;
import static android.hardware.usb.UsbPortStatus.POWER_ROLE_NONE;
import static android.hardware.usb.UsbPortStatus.POWER_ROLE_SINK;
import static android.hardware.usb.UsbPortStatus.POWER_ROLE_SOURCE;

import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.hardware.usb.V1_0.Constants;

import com.android.internal.util.Preconditions;

import java.util.Objects;

/**
 * Represents a physical USB port and describes its characteristics.
 *
 * @hide
 */
@SystemApi
public final class UsbPort {
    private final String mId;
    private final int mSupportedModes;
    private final UsbManager mUsbManager;
    private final int mSupportedContaminantProtectionModes;
    private final boolean mSupportsEnableContaminantPresenceProtection;
    private final boolean mSupportsEnableContaminantPresenceDetection;

    private static final int NUM_DATA_ROLES = Constants.PortDataRole.NUM_DATA_ROLES;
    /**
     * Points to the first power role in the IUsb HAL.
     */
    private static final int POWER_ROLE_OFFSET = Constants.PortPowerRole.NONE;

    /** @hide */
    public UsbPort(@NonNull UsbManager usbManager, @NonNull String id, int supportedModes,
            int supportedContaminantProtectionModes,
            boolean supportsEnableContaminantPresenceProtection,
            boolean supportsEnableContaminantPresenceDetection) {
        Objects.requireNonNull(id);
        Preconditions.checkFlagsArgument(supportedModes,
                MODE_DFP | MODE_UFP | MODE_AUDIO_ACCESSORY | MODE_DEBUG_ACCESSORY);

        mUsbManager = usbManager;
        mId = id;
        mSupportedModes = supportedModes;
        mSupportedContaminantProtectionModes = supportedContaminantProtectionModes;
        mSupportsEnableContaminantPresenceProtection =
                supportsEnableContaminantPresenceProtection;
        mSupportsEnableContaminantPresenceDetection =
                supportsEnableContaminantPresenceDetection;
    }

    /**
     * Gets the unique id of the port.
     *
     * @return The unique id of the port; not intended for display.
     *
     * @hide
     */
    public String getId() {
        return mId;
    }

    /**
     * Gets the supported modes of the port.
     * <p>
     * The actual mode of the port may vary depending on what is plugged into it.
     * </p>
     *
     * @return The supported modes: one of {@link UsbPortStatus#MODE_DFP},
     * {@link UsbPortStatus#MODE_UFP}, or {@link UsbPortStatus#MODE_DUAL}.
     *
     * @hide
     */
    public int getSupportedModes() {
        return mSupportedModes;
    }

   /**
     * Gets the supported port proctection modes when the port is contaminated.
     * <p>
     * The actual mode of the port is decided by the hardware
     * </p>
     *
     * @hide
     */
    public int getSupportedContaminantProtectionModes() {
        return mSupportedContaminantProtectionModes;
    }

   /**
     * Tells if UsbService can enable/disable contaminant presence protection.
     *
     * @hide
     */
    public boolean supportsEnableContaminantPresenceProtection() {
        return mSupportsEnableContaminantPresenceProtection;
    }

   /**
     * Tells if UsbService can enable/disable contaminant presence detection.
     *
     * @hide
     */
    public boolean supportsEnableContaminantPresenceDetection() {
        return mSupportsEnableContaminantPresenceDetection;
    }

    /**
     * Gets the status of this USB port.
     *
     * @return The status of the this port, or {@code null} if port is unknown.
     */
    @RequiresPermission(Manifest.permission.MANAGE_USB)
    public @Nullable UsbPortStatus getStatus() {
        return mUsbManager.getPortStatus(this);
    }

    /**
     * Sets the desired role combination of the port.
     * <p>
     * The supported role combinations depend on what is connected to the port and may be
     * determined by consulting
     * {@link UsbPortStatus#isRoleCombinationSupported UsbPortStatus.isRoleCombinationSupported}.
     * </p><p>
     * Note: This function is asynchronous and may fail silently without applying
     * the requested changes.  If this function does cause a status change to occur then
     * a {@link UsbManager#ACTION_USB_PORT_CHANGED} broadcast will be sent.
     * </p>
     *
     * @param powerRole The desired power role: {@link UsbPortStatus#POWER_ROLE_SOURCE} or
     *                  {@link UsbPortStatus#POWER_ROLE_SINK}, or
     *                  {@link UsbPortStatus#POWER_ROLE_NONE} if no power role.
     * @param dataRole The desired data role: {@link UsbPortStatus#DATA_ROLE_HOST} or
     *                 {@link UsbPortStatus#DATA_ROLE_DEVICE}, or
     *                 {@link UsbPortStatus#DATA_ROLE_NONE} if no data role.
     */
    @RequiresPermission(Manifest.permission.MANAGE_USB)
    public void setRoles(@UsbPortStatus.UsbPowerRole int powerRole,
            @UsbPortStatus.UsbDataRole int dataRole) {
        UsbPort.checkRoles(powerRole, dataRole);

        mUsbManager.setPortRoles(this, powerRole, dataRole);
    }

    /**
     * @hide
     **/
    public void enableContaminantDetection(boolean enable) {
        mUsbManager.enableContaminantDetection(this, enable);
    }
    /**
     * Combines one power and one data role together into a unique value with
     * exactly one bit set.  This can be used to efficiently determine whether
     * a combination of roles is supported by testing whether that bit is present
     * in a bit-field.
     *
     * @param powerRole The desired power role: {@link UsbPortStatus#POWER_ROLE_SOURCE}
     *                  or {@link UsbPortStatus#POWER_ROLE_SINK}, or 0 if no power role.
     * @param dataRole  The desired data role: {@link UsbPortStatus#DATA_ROLE_HOST}
     *                  or {@link UsbPortStatus#DATA_ROLE_DEVICE}, or 0 if no data role.
     * @hide
     */
    public static int combineRolesAsBit(int powerRole, int dataRole) {
        checkRoles(powerRole, dataRole);
        final int index = ((powerRole - POWER_ROLE_OFFSET) * NUM_DATA_ROLES) + dataRole;
        return 1 << index;
    }

    /** @hide */
    public static String modeToString(int mode) {
        StringBuilder modeString = new StringBuilder();
        if (mode == MODE_NONE) {
            return "none";
        }

        if ((mode & MODE_DUAL) == MODE_DUAL) {
            modeString.append("dual, ");
        } else {
            if ((mode & MODE_DFP) == MODE_DFP) {
                modeString.append("dfp, ");
            } else if ((mode & MODE_UFP) == MODE_UFP) {
                modeString.append("ufp, ");
            }
        }
        if ((mode & MODE_AUDIO_ACCESSORY) == MODE_AUDIO_ACCESSORY) {
            modeString.append("audio_acc, ");
        }
        if ((mode & MODE_DEBUG_ACCESSORY) == MODE_DEBUG_ACCESSORY) {
            modeString.append("debug_acc, ");
        }

        if (modeString.length() == 0) {
            return Integer.toString(mode);
        }
        return modeString.substring(0, modeString.length() - 2);
    }

    /** @hide */
    public static String powerRoleToString(int role) {
        switch (role) {
            case POWER_ROLE_NONE:
                return "no-power";
            case POWER_ROLE_SOURCE:
                return "source";
            case POWER_ROLE_SINK:
                return "sink";
            default:
                return Integer.toString(role);
        }
    }

    /** @hide */
    public static String dataRoleToString(int role) {
        switch (role) {
            case DATA_ROLE_NONE:
                return "no-data";
            case DATA_ROLE_HOST:
                return "host";
            case DATA_ROLE_DEVICE:
                return "device";
            default:
                return Integer.toString(role);
        }
    }

    /** @hide */
    public static String contaminantPresenceStatusToString(int contaminantPresenceStatus) {
        switch (contaminantPresenceStatus) {
            case CONTAMINANT_DETECTION_NOT_SUPPORTED:
                return "not-supported";
            case CONTAMINANT_DETECTION_DISABLED:
                return "disabled";
            case CONTAMINANT_DETECTION_DETECTED:
                return "detected";
            case CONTAMINANT_DETECTION_NOT_DETECTED:
                return "not detected";
            default:
                return Integer.toString(contaminantPresenceStatus);
        }
    }

    /** @hide */
    public static String roleCombinationsToString(int combo) {
        StringBuilder result = new StringBuilder();
        result.append("[");

        boolean first = true;
        while (combo != 0) {
            final int index = Integer.numberOfTrailingZeros(combo);
            combo &= ~(1 << index);
            final int powerRole = (index / NUM_DATA_ROLES + POWER_ROLE_OFFSET);
            final int dataRole = index % NUM_DATA_ROLES;
            if (first) {
                first = false;
            } else {
                result.append(", ");
            }
            result.append(powerRoleToString(powerRole));
            result.append(':');
            result.append(dataRoleToString(dataRole));
        }

        result.append("]");
        return result.toString();
    }

    /** @hide */
    public static void checkMode(int powerRole) {
        Preconditions.checkArgumentInRange(powerRole, Constants.PortMode.NONE,
                Constants.PortMode.NUM_MODES - 1, "portMode");
    }

    /** @hide */
    public static void checkPowerRole(int dataRole) {
        Preconditions.checkArgumentInRange(dataRole, Constants.PortPowerRole.NONE,
                Constants.PortPowerRole.NUM_POWER_ROLES - 1, "powerRole");
    }

    /** @hide */
    public static void checkDataRole(int mode) {
        Preconditions.checkArgumentInRange(mode, Constants.PortDataRole.NONE,
                Constants.PortDataRole.NUM_DATA_ROLES - 1, "powerRole");
    }

    /** @hide */
    public static void checkRoles(int powerRole, int dataRole) {
        Preconditions.checkArgumentInRange(powerRole, POWER_ROLE_NONE, POWER_ROLE_SINK,
                "powerRole");
        Preconditions.checkArgumentInRange(dataRole, DATA_ROLE_NONE, DATA_ROLE_DEVICE, "dataRole");
    }

    /** @hide */
    public boolean isModeSupported(int mode) {
        if ((mSupportedModes & mode) == mode) return true;
        return false;
    }

    @NonNull
    @Override
    public String toString() {
        return "UsbPort{id=" + mId + ", supportedModes=" + modeToString(mSupportedModes)
                + "supportedContaminantProtectionModes=" + mSupportedContaminantProtectionModes
                + "supportsEnableContaminantPresenceProtection="
                + mSupportsEnableContaminantPresenceProtection
                + "supportsEnableContaminantPresenceDetection="
                + mSupportsEnableContaminantPresenceDetection;
    }
}
