/*
 * 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 com.android.settings.deviceinfo;

import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.hardware.usb.UsbManager;
import android.hardware.usb.UsbPort;
import android.hardware.usb.UsbPortStatus;
import android.os.UserHandle;
import android.os.UserManager;
import android.support.annotation.VisibleForTesting;

public class UsbBackend {

    public static final int MODE_POWER_MASK  = 0x01;
    public static final int MODE_POWER_SINK   = 0x00;
    public static final int MODE_POWER_SOURCE = 0x01;

    public static final int MODE_DATA_MASK  = 0x03 << 1;
    public static final int MODE_DATA_NONE   = 0x00 << 1;
    public static final int MODE_DATA_MTP    = 0x01 << 1;
    public static final int MODE_DATA_PTP    = 0x02 << 1;
    public static final int MODE_DATA_MIDI   = 0x03 << 1;

    private final boolean mRestricted;
    private final boolean mRestrictedBySystem;
    private final boolean mMidi;

    private UsbManager mUsbManager;
    private UsbPort mPort;
    private UsbPortStatus mPortStatus;

    private Context mContext;

    public UsbBackend(Context context) {
        this(context, new UserRestrictionUtil(context));
    }

    @VisibleForTesting
    public UsbBackend(Context context, UserRestrictionUtil userRestrictionUtil) {
        mContext = context;
        mUsbManager = context.getSystemService(UsbManager.class);

        mRestricted = userRestrictionUtil.isUsbFileTransferRestricted();
        mRestrictedBySystem = userRestrictionUtil.isUsbFileTransferRestrictedBySystem();
        mMidi = context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_MIDI);

        UsbPort[] ports = mUsbManager.getPorts();
        if (ports == null) {
            return;
        }
        // For now look for a connected port, in the future we should identify port in the
        // notification and pick based on that.
        final int N = ports.length;
        for (int i = 0; i < N; i++) {
            UsbPortStatus status = mUsbManager.getPortStatus(ports[i]);
            if (status.isConnected()) {
                mPort = ports[i];
                mPortStatus = status;
                break;
            }
        }
    }

    public int getCurrentMode() {
        if (mPort != null) {
            int power = mPortStatus.getCurrentPowerRole() == UsbPort.POWER_ROLE_SOURCE
                    ? MODE_POWER_SOURCE : MODE_POWER_SINK;
            return power | getUsbDataMode();
        }
        return MODE_POWER_SINK | getUsbDataMode();
    }

    public int getUsbDataMode() {
        if (!isUsbDataUnlocked()) {
            return MODE_DATA_NONE;
        } else if (mUsbManager.isFunctionEnabled(UsbManager.USB_FUNCTION_MTP)) {
            return MODE_DATA_MTP;
        } else if (mUsbManager.isFunctionEnabled(UsbManager.USB_FUNCTION_PTP)) {
            return MODE_DATA_PTP;
        } else if (mUsbManager.isFunctionEnabled(UsbManager.USB_FUNCTION_MIDI)) {
            return MODE_DATA_MIDI;
        }
        return MODE_DATA_NONE; // ...
    }

    private boolean isUsbDataUnlocked() {
        Intent intent = mContext.registerReceiver(null,
            new IntentFilter(UsbManager.ACTION_USB_STATE));
        return intent == null ?
            false : intent.getBooleanExtra(UsbManager.USB_DATA_UNLOCKED, false);
    }

    private void setUsbFunction(int mode) {
        switch (mode) {
            case MODE_DATA_MTP:
                mUsbManager.setCurrentFunction(UsbManager.USB_FUNCTION_MTP, true);
                break;
            case MODE_DATA_PTP:
                mUsbManager.setCurrentFunction(UsbManager.USB_FUNCTION_PTP, true);
                break;
            case MODE_DATA_MIDI:
                mUsbManager.setCurrentFunction(UsbManager.USB_FUNCTION_MIDI, true);
                break;
            default:
                mUsbManager.setCurrentFunction(null, false);
                break;
        }
    }

    public void setMode(int mode) {
        if (mPort != null) {
            int powerRole = modeToPower(mode);
            // If we aren't using any data modes and we support host mode, then go to host mode
            // so maybe? the other device can provide data if it wants, otherwise go into device
            // mode because we have no choice.
            int dataRole = (mode & MODE_DATA_MASK) == MODE_DATA_NONE
                    && mPortStatus.isRoleCombinationSupported(powerRole, UsbPort.DATA_ROLE_HOST)
                    ? UsbPort.DATA_ROLE_HOST : UsbPort.DATA_ROLE_DEVICE;
            mUsbManager.setPortRoles(mPort, powerRole, dataRole);
        }
        setUsbFunction(mode & MODE_DATA_MASK);
    }

    private int modeToPower(int mode) {
        return (mode & MODE_POWER_MASK) == MODE_POWER_SOURCE
                    ? UsbPort.POWER_ROLE_SOURCE : UsbPort.POWER_ROLE_SINK;
    }

    public boolean isModeDisallowed(int mode) {
        if (mRestricted && (mode & MODE_DATA_MASK) != MODE_DATA_NONE
                && (mode & MODE_DATA_MASK) != MODE_DATA_MIDI) {
            // No USB data modes are supported.
            return true;
        }
        return false;
    }

    public boolean isModeDisallowedBySystem(int mode) {
        if (mRestrictedBySystem && (mode & MODE_DATA_MASK) != MODE_DATA_NONE
                && (mode & MODE_DATA_MASK) != MODE_DATA_MIDI) {
            // No USB data modes are supported.
            return true;
        }
        return false;
    }

    public boolean isModeSupported(int mode) {
        if (!mMidi && (mode & MODE_DATA_MASK) == MODE_DATA_MIDI) {
            return false;
        }

        if (mPort != null) {
            int power = modeToPower(mode);
            if ((mode & MODE_DATA_MASK) != 0) {
                // We have a port and data, need to be in device mode.
                return mPortStatus.isRoleCombinationSupported(power,
                        UsbPort.DATA_ROLE_DEVICE);
            } else {
                // No data needed, we can do this power mode in either device or host.
                return mPortStatus.isRoleCombinationSupported(power, UsbPort.DATA_ROLE_DEVICE)
                        || mPortStatus.isRoleCombinationSupported(power, UsbPort.DATA_ROLE_HOST);
            }
        }
        // No port, support sink modes only.
        return (mode & MODE_POWER_MASK) != MODE_POWER_SOURCE;
    }

    // Wrapper class to enable testing with UserManager APIs
    public static class UserRestrictionUtil {
        private UserManager mUserManager;

        public UserRestrictionUtil(Context context) {
            mUserManager = UserManager.get(context);
        }

        public boolean isUsbFileTransferRestricted() {
            return mUserManager.hasUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER);
        }

        public boolean isUsbFileTransferRestrictedBySystem() {
            return mUserManager.hasBaseUserRestriction(
                UserManager.DISALLOW_USB_FILE_TRANSFER, UserHandle.of(UserHandle.myUserId()));
        }
    }
}
