/*
 * Copyright (C) 2016 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.bluetooth.avrcpcontroller;

import android.bluetooth.BluetoothAvrcpPlayerSettings;
import android.util.Log;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

/*
 * Contains information Player Application Setting extended from BluetootAvrcpPlayerSettings
 */
class PlayerApplicationSettings {
    private static final String TAG = "PlayerApplicationSettings";

    /*
     * Values for SetPlayerApplicationSettings from AVRCP Spec V1.6 Appendix F.
     */
    private static final byte JNI_ATTRIB_EQUALIZER_STATUS = 0x01;
    private static final byte JNI_ATTRIB_REPEAT_STATUS = 0x02;
    private static final byte JNI_ATTRIB_SHUFFLE_STATUS = 0x03;
    private static final byte JNI_ATTRIB_SCAN_STATUS = 0x04;

    private static final byte JNI_EQUALIZER_STATUS_OFF = 0x01;
    private static final byte JNI_EQUALIZER_STATUS_ON = 0x02;

    private static final byte JNI_REPEAT_STATUS_OFF = 0x01;
    private static final byte JNI_REPEAT_STATUS_SINGLE_TRACK_REPEAT = 0x02;
    private static final byte JNI_REPEAT_STATUS_ALL_TRACK_REPEAT = 0x03;
    private static final byte JNI_REPEAT_STATUS_GROUP_REPEAT = 0x04;

    private static final byte JNI_SHUFFLE_STATUS_OFF = 0x01;
    private static final byte JNI_SHUFFLE_STATUS_ALL_TRACK_SHUFFLE = 0x02;
    private static final byte JNI_SHUFFLE_STATUS_GROUP_SHUFFLE = 0x03;

    private static final byte JNI_SCAN_STATUS_OFF = 0x01;
    private static final byte JNI_SCAN_STATUS_ALL_TRACK_SCAN = 0x02;
    private static final byte JNI_SCAN_STATUS_GROUP_SCAN = 0x03;

    private static final byte JNI_STATUS_INVALID = -1;


    /*
     * Hash map of current settings.
     */
    private Map<Integer, Integer> mSettings = new HashMap<Integer, Integer>();

    /*
     * Hash map of supported values, a setting should be supported by the remote in order to enable
     * in mSettings.
     */
    private Map<Integer, ArrayList<Integer>> mSupportedValues =
            new HashMap<Integer, ArrayList<Integer>>();

    /* Convert from JNI array to Java classes. */
    static PlayerApplicationSettings makeSupportedSettings(byte[] btAvrcpAttributeList) {
        PlayerApplicationSettings newObj = new PlayerApplicationSettings();
        try {
            for (int i = 0; i < btAvrcpAttributeList.length; ) {
                byte attrId = btAvrcpAttributeList[i++];
                byte numSupportedVals = btAvrcpAttributeList[i++];
                ArrayList<Integer> supportedValues = new ArrayList<Integer>();

                for (int j = 0; j < numSupportedVals; j++) {
                    // Yes, keep using i for array indexing.
                    supportedValues.add(
                            mapAttribIdValtoAvrcpPlayerSetting(attrId, btAvrcpAttributeList[i++]));
                }
                newObj.mSupportedValues.put(mapBTAttribIdToAvrcpPlayerSettings(attrId),
                        supportedValues);
            }
        } catch (ArrayIndexOutOfBoundsException exception) {
            Log.e(TAG, "makeSupportedSettings attributeList index error.");
        }
        return newObj;
    }

    public BluetoothAvrcpPlayerSettings getAvrcpSettings() {
        int supportedSettings = 0;
        for (Integer setting : mSettings.keySet()) {
            supportedSettings |= setting;
        }
        BluetoothAvrcpPlayerSettings result = new BluetoothAvrcpPlayerSettings(supportedSettings);
        for (Integer setting : mSettings.keySet()) {
            result.addSettingValue(setting, mSettings.get(setting));
        }
        return result;
    }

    static PlayerApplicationSettings makeSettings(byte[] btAvrcpAttributeList) {
        PlayerApplicationSettings newObj = new PlayerApplicationSettings();
        try {
            for (int i = 0; i < btAvrcpAttributeList.length; ) {
                byte attrId = btAvrcpAttributeList[i++];

                newObj.mSettings.put(mapBTAttribIdToAvrcpPlayerSettings(attrId),
                        mapAttribIdValtoAvrcpPlayerSetting(attrId, btAvrcpAttributeList[i++]));
            }
        } catch (ArrayIndexOutOfBoundsException exception) {
            Log.e(TAG, "makeSettings JNI_ATTRIButeList index error.");
        }
        return newObj;
    }

    public void setSupport(PlayerApplicationSettings updates) {
        mSettings = updates.mSettings;
        mSupportedValues = updates.mSupportedValues;
    }

    public void setValues(BluetoothAvrcpPlayerSettings updates) {
        int supportedSettings = updates.getSettings();
        for (int i = 1; i <= BluetoothAvrcpPlayerSettings.SETTING_SCAN; i++) {
            if ((i & supportedSettings) > 0) {
                mSettings.put(i, updates.getSettingValue(i));
            }
        }
    }

    /*
     * Check through all settings to ensure that they are all available to be set and then check
     * that the desired value is in fact supported by our remote player.
     */
    public boolean supportsSettings(BluetoothAvrcpPlayerSettings settingsToCheck) {
        int settingSubset = settingsToCheck.getSettings();
        int supportedSettings = 0;
        for (Integer setting : mSupportedValues.keySet()) {
            supportedSettings |= setting;
        }
        try {
            if ((supportedSettings & settingSubset) == settingSubset) {
                for (Integer settingId : mSettings.keySet()) {
                    // The setting is in both settings to check and supported settings but the
                    // value is not supported.
                    if ((settingId & settingSubset) == settingId && (!mSupportedValues.get(
                            settingId).contains(settingsToCheck.getSettingValue(settingId)))) {
                        return false;
                    }
                }
                return true;
            }
        } catch (NullPointerException e) {
            Log.e(TAG,
                    "supportsSettings received a supported setting that has no supported values.");
        }
        return false;
    }

    // Convert currently desired settings into an attribute array to pass to the native layer to
    // enable them.
    public ArrayList<Byte> getNativeSettings() {
        int i = 0;
        ArrayList<Byte> attribArray = new ArrayList<Byte>();
        for (Integer settingId : mSettings.keySet()) {
            switch (settingId) {
                case BluetoothAvrcpPlayerSettings.SETTING_EQUALIZER:
                    attribArray.add(JNI_ATTRIB_EQUALIZER_STATUS);
                    attribArray.add(mapAvrcpPlayerSettingstoBTattribVal(settingId,
                            mSettings.get(settingId)));
                    break;
                case BluetoothAvrcpPlayerSettings.SETTING_REPEAT:
                    attribArray.add(JNI_ATTRIB_REPEAT_STATUS);
                    attribArray.add(mapAvrcpPlayerSettingstoBTattribVal(settingId,
                            mSettings.get(settingId)));
                    break;
                case BluetoothAvrcpPlayerSettings.SETTING_SHUFFLE:
                    attribArray.add(JNI_ATTRIB_SHUFFLE_STATUS);
                    attribArray.add(mapAvrcpPlayerSettingstoBTattribVal(settingId,
                            mSettings.get(settingId)));
                    break;
                case BluetoothAvrcpPlayerSettings.SETTING_SCAN:
                    attribArray.add(JNI_ATTRIB_SCAN_STATUS);
                    attribArray.add(mapAvrcpPlayerSettingstoBTattribVal(settingId,
                            mSettings.get(settingId)));
                    break;
                default:
                    Log.w(TAG, "Unknown setting found in getNativeSettings: " + settingId);
            }
        }
        return attribArray;
    }

    // Convert a native Attribute Id/Value pair into the AVRCP equivalent value.
    private static int mapAttribIdValtoAvrcpPlayerSetting(byte attribId, byte attribVal) {
        if (attribId == JNI_ATTRIB_EQUALIZER_STATUS) {
            switch (attribVal) {
                case JNI_EQUALIZER_STATUS_OFF:
                    return BluetoothAvrcpPlayerSettings.STATE_OFF;
                case JNI_EQUALIZER_STATUS_ON:
                    return BluetoothAvrcpPlayerSettings.STATE_ON;
            }
        } else if (attribId == JNI_ATTRIB_REPEAT_STATUS) {
            switch (attribVal) {
                case JNI_REPEAT_STATUS_ALL_TRACK_REPEAT:
                    return BluetoothAvrcpPlayerSettings.STATE_ALL_TRACK;
                case JNI_REPEAT_STATUS_GROUP_REPEAT:
                    return BluetoothAvrcpPlayerSettings.STATE_GROUP;
                case JNI_REPEAT_STATUS_OFF:
                    return BluetoothAvrcpPlayerSettings.STATE_OFF;
                case JNI_REPEAT_STATUS_SINGLE_TRACK_REPEAT:
                    return BluetoothAvrcpPlayerSettings.STATE_SINGLE_TRACK;
            }
        } else if (attribId == JNI_ATTRIB_SCAN_STATUS) {
            switch (attribVal) {
                case JNI_SCAN_STATUS_ALL_TRACK_SCAN:
                    return BluetoothAvrcpPlayerSettings.STATE_ALL_TRACK;
                case JNI_SCAN_STATUS_GROUP_SCAN:
                    return BluetoothAvrcpPlayerSettings.STATE_GROUP;
                case JNI_SCAN_STATUS_OFF:
                    return BluetoothAvrcpPlayerSettings.STATE_OFF;
            }
        } else if (attribId == JNI_ATTRIB_SHUFFLE_STATUS) {
            switch (attribVal) {
                case JNI_SHUFFLE_STATUS_ALL_TRACK_SHUFFLE:
                    return BluetoothAvrcpPlayerSettings.STATE_ALL_TRACK;
                case JNI_SHUFFLE_STATUS_GROUP_SHUFFLE:
                    return BluetoothAvrcpPlayerSettings.STATE_GROUP;
                case JNI_SHUFFLE_STATUS_OFF:
                    return BluetoothAvrcpPlayerSettings.STATE_OFF;
            }
        }
        return BluetoothAvrcpPlayerSettings.STATE_INVALID;
    }

    // Convert an AVRCP Setting/Value pair into the native equivalent value;
    private static byte mapAvrcpPlayerSettingstoBTattribVal(int mSetting, int mSettingVal) {
        if (mSetting == BluetoothAvrcpPlayerSettings.SETTING_EQUALIZER) {
            switch (mSettingVal) {
                case BluetoothAvrcpPlayerSettings.STATE_OFF:
                    return JNI_EQUALIZER_STATUS_OFF;
                case BluetoothAvrcpPlayerSettings.STATE_ON:
                    return JNI_EQUALIZER_STATUS_ON;
            }
        } else if (mSetting == BluetoothAvrcpPlayerSettings.SETTING_REPEAT) {
            switch (mSettingVal) {
                case BluetoothAvrcpPlayerSettings.STATE_OFF:
                    return JNI_REPEAT_STATUS_OFF;
                case BluetoothAvrcpPlayerSettings.STATE_SINGLE_TRACK:
                    return JNI_REPEAT_STATUS_SINGLE_TRACK_REPEAT;
                case BluetoothAvrcpPlayerSettings.STATE_ALL_TRACK:
                    return JNI_REPEAT_STATUS_ALL_TRACK_REPEAT;
                case BluetoothAvrcpPlayerSettings.STATE_GROUP:
                    return JNI_REPEAT_STATUS_GROUP_REPEAT;
            }
        } else if (mSetting == BluetoothAvrcpPlayerSettings.SETTING_SHUFFLE) {
            switch (mSettingVal) {
                case BluetoothAvrcpPlayerSettings.STATE_OFF:
                    return JNI_SHUFFLE_STATUS_OFF;
                case BluetoothAvrcpPlayerSettings.STATE_ALL_TRACK:
                    return JNI_SHUFFLE_STATUS_ALL_TRACK_SHUFFLE;
                case BluetoothAvrcpPlayerSettings.STATE_GROUP:
                    return JNI_SHUFFLE_STATUS_GROUP_SHUFFLE;
            }
        } else if (mSetting == BluetoothAvrcpPlayerSettings.SETTING_SCAN) {
            switch (mSettingVal) {
                case BluetoothAvrcpPlayerSettings.STATE_OFF:
                    return JNI_SCAN_STATUS_OFF;
                case BluetoothAvrcpPlayerSettings.STATE_ALL_TRACK:
                    return JNI_SCAN_STATUS_ALL_TRACK_SCAN;
                case BluetoothAvrcpPlayerSettings.STATE_GROUP:
                    return JNI_SCAN_STATUS_GROUP_SCAN;
            }
        }
        return JNI_STATUS_INVALID;
    }

    // convert a native Attribute Id into the AVRCP Setting equivalent value;
    private static int mapBTAttribIdToAvrcpPlayerSettings(byte attribId) {
        switch (attribId) {
            case JNI_ATTRIB_EQUALIZER_STATUS:
                return BluetoothAvrcpPlayerSettings.SETTING_EQUALIZER;
            case JNI_ATTRIB_REPEAT_STATUS:
                return BluetoothAvrcpPlayerSettings.SETTING_REPEAT;
            case JNI_ATTRIB_SHUFFLE_STATUS:
                return BluetoothAvrcpPlayerSettings.SETTING_SHUFFLE;
            case JNI_ATTRIB_SCAN_STATUS:
                return BluetoothAvrcpPlayerSettings.SETTING_SCAN;
            default:
                return BluetoothAvrcpPlayerSettings.STATE_INVALID;
        }
    }

}

