/*
 * 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.avrcp;

import android.annotation.NonNull;
import android.content.ComponentName;
import android.content.Context;
import android.media.MediaDescription;
import android.media.MediaMetadata;
import android.media.browse.MediaBrowser;
import android.media.browse.MediaBrowser.MediaItem;
import android.media.session.MediaSession;
import android.media.session.MediaSession.QueueItem;
import android.os.Bundle;
import android.util.Log;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;

/*************************************************************************************************
 * Provides functionality required for Browsed Media Player like browsing Virtual File System, get
 * Item Attributes, play item from the file system, etc.
 * Acts as an Interface to communicate with Media Browsing APIs for browsing FileSystem.
 ************************************************************************************************/

class BrowsedMediaPlayer {
    private static final boolean DEBUG = false;
    private static final String TAG = "BrowsedMediaPlayer";

    /* connection state with MediaBrowseService */
    private static final int DISCONNECTED = 0;
    private static final int CONNECTED = 1;
    private static final int SUSPENDED = 2;

    private static final String[] ROOT_FOLDER = {"root"};

    /*  package and service name of target Media Player which is set for browsing */
    private String mPackageName;
    private String mClassName;
    private Context mContext;
    private AvrcpMediaRspInterface mMediaInterface;
    private byte[] mBDAddr;

    /* Object used to connect to MediaBrowseService of Media Player */
    private MediaBrowser mMediaBrowser = null;
    private MediaController mMediaController = null;

    /* The mediaId to be used for subscribing for children using the MediaBrowser */
    private String mMediaId = null;
    private String mRootFolderUid = null;
    private int mConnState = DISCONNECTED;

    /* stores the path trail during changePath */
    private Stack<String> mPathStack = null;

    /* Number of items in current folder */
    private int mCurrFolderNumItems = 0;

    /* store mapping between uid(Avrcp) and mediaId(Media Player). */
    private HashMap<Integer, String> mHmap = new HashMap<Integer, String>();

    /* command objects from avrcp handler */
    private AvrcpCmd.FolderItemsCmd mFolderItemsReqObj;

    /* store result of getfolderitems with scope="vfs" */
    private List<MediaBrowser.MediaItem> mFolderItems = null;

    /* Connection state callback handler */
    private MediaBrowser.ConnectionCallback browseMediaConnectionCallback =
            new MediaBrowser.ConnectionCallback() {

        @Override
        public void onConnected() {
            mConnState = CONNECTED;
            if (DEBUG) Log.d(TAG, "mediaBrowser CONNECTED to " + mPackageName);
            /* perform init tasks and set player as browsed player on successful connection */
            onBrowseConnect();
        }

        @Override
        public void onConnectionFailed() {
            mConnState = DISCONNECTED;
            Log.e(TAG, "mediaBrowser Connection failed with " + mPackageName
                    + ", Sending fail response!");
            mMediaInterface.setBrowsedPlayerRsp(mBDAddr, AvrcpConstants.RSP_INTERNAL_ERR,
                (byte)0x00, 0, null);
        }

        @Override
        public void onConnectionSuspended() {
            mConnState = SUSPENDED;
            Log.e(TAG, "mediaBrowser SUSPENDED connection with " + mPackageName);
        }
    };

    /* Subscription callback handler. Subscribe to a folder to get its contents */
    private MediaBrowser.SubscriptionCallback folderItemsCb =
            new MediaBrowser.SubscriptionCallback() {

        @Override
        public void onChildrenLoaded(String parentId, List<MediaBrowser.MediaItem> children) {
            if (DEBUG) Log.d(TAG, "OnChildren Loaded folder items: childrens= " + children.size());

            /*
             * cache current folder items and send as rsp when remote requests
             * get_folder_items (scope = vfs)
             */
            if (mFolderItems == null) {
                if (DEBUG) Log.d(TAG, "sending setbrowsed player rsp");
                mFolderItems = children;
                mMediaInterface.setBrowsedPlayerRsp(mBDAddr, AvrcpConstants.RSP_NO_ERROR,
                        (byte)0x00, children.size(), ROOT_FOLDER);
            } else {
                mFolderItems = children;
                mCurrFolderNumItems = mFolderItems.size();
                mMediaInterface.changePathRsp(mBDAddr, AvrcpConstants.RSP_NO_ERROR,
                        mCurrFolderNumItems);
            }
            mMediaBrowser.unsubscribe(parentId);
        }

        /* UID is invalid */
        @Override
        public void onError(String id) {
            Log.e(TAG, "set browsed player rsp. Could not get root folder items");
            mMediaInterface.setBrowsedPlayerRsp(mBDAddr, AvrcpConstants.RSP_INTERNAL_ERR,
                    (byte)0x00, 0, null);
        }
    };

    /* callback from media player in response to getitemAttr request */
    private class ItemAttribSubscriber extends MediaBrowser.SubscriptionCallback {
        private String mMediaId;
        private AvrcpCmd.ItemAttrCmd mAttrReq;

        public ItemAttribSubscriber(
                @NonNull AvrcpCmd.ItemAttrCmd attrReq, @NonNull String mediaId) {
            mAttrReq = attrReq;
            mMediaId = mediaId;
        }

        @Override
        public void onChildrenLoaded(String parentId, List<MediaBrowser.MediaItem> children) {
            String logprefix = "ItemAttribSubscriber(" + mMediaId + "): ";
            if (DEBUG) Log.d(TAG, logprefix + "OnChildren Loaded");
            int status = AvrcpConstants.RSP_INV_ITEM;

            if (children == null) {
                Log.w(TAG, logprefix + "children list is null parentId: " + parentId);
            } else {
                /* find the item in the folder */
                for (MediaBrowser.MediaItem item : children) {
                    if (item.getMediaId().equals(mMediaId)) {
                        if (DEBUG) Log.d(TAG, logprefix + "found item");
                        getItemAttrFilterAttr(item);
                        status = AvrcpConstants.RSP_NO_ERROR;
                        break;
                    }
                }
            }
            /* Send only error from here, in case of success, getItemAttrFilterAttr sends */
            if (status != AvrcpConstants.RSP_NO_ERROR) {
                Log.e(TAG, logprefix + "not able to find item from " + parentId);
                mMediaInterface.getItemAttrRsp(mBDAddr, status, null);
            }
            mMediaBrowser.unsubscribe(parentId);
        }

        @Override
        public void onError(String id) {
            Log.e(TAG, "Could not get attributes from media player id: " + id);
            mMediaInterface.getItemAttrRsp(mBDAddr, AvrcpConstants.RSP_INTERNAL_ERR, null);
        }

        /* helper method to filter required attibuteand send GetItemAttr response */
        private void getItemAttrFilterAttr(@NonNull MediaBrowser.MediaItem mediaItem) {
            /* Response parameters */
            int[] attrIds = null; /* array of attr ids */
            String[] attrValues = null; /* array of attr values */

            /* variables to temperorily add attrs */
            ArrayList<Integer> attrIdArray = new ArrayList<Integer>();
            ArrayList<String> attrValueArray = new ArrayList<String>();
            ArrayList<Integer> attrReqIds = new ArrayList<Integer>();

            if (mAttrReq.mNumAttr == AvrcpConstants.NUM_ATTR_NONE) {
                // Note(jamuraa): the stack should never send this, remove?
                Log.i(TAG, "getItemAttrFilterAttr: No attributes requested");
                mMediaInterface.getItemAttrRsp(mBDAddr, AvrcpConstants.RSP_BAD_PARAM, null);
                return;
            }

            /* check if remote device has requested all attributes */
            if (mAttrReq.mNumAttr == AvrcpConstants.NUM_ATTR_ALL
                    || mAttrReq.mNumAttr == AvrcpConstants.MAX_NUM_ATTR) {
                for (int idx = 1; idx <= AvrcpConstants.MAX_NUM_ATTR; idx++) {
                    attrReqIds.add(idx); /* attr id 0x00 is unused */
                }
            } else {
                /* get only the requested attribute ids from the request */
                for (int idx = 0; idx < mAttrReq.mNumAttr; idx++) {
                    attrReqIds.add(mAttrReq.mAttrIDs[idx]);
                }
            }

            /* lookup and copy values of attributes for ids requested above */
            for (int attrId : attrReqIds) {
                /* check if media player provided requested attributes */
                String value = getAttrValue(attrId, mediaItem);
                if (value != null) {
                    attrIdArray.add(attrId);
                    attrValueArray.add(value);
                }
            }

            /* copy filtered attr ids and attr values to response parameters */
            attrIds = new int[attrIdArray.size()];
            for (int i = 0; i < attrIdArray.size(); i++) attrIds[i] = attrIdArray.get(i);

            attrValues = attrValueArray.toArray(new String[attrIdArray.size()]);

            /* create rsp object and send response */
            ItemAttrRsp rspObj = new ItemAttrRsp(AvrcpConstants.RSP_NO_ERROR, attrIds, attrValues);
            mMediaInterface.getItemAttrRsp(mBDAddr, AvrcpConstants.RSP_NO_ERROR, rspObj);
        }
    }

    /* Constructor */
    public BrowsedMediaPlayer(byte[] address, Context context,
            AvrcpMediaRspInterface mAvrcpMediaRspInterface) {
        mContext = context;
        mMediaInterface = mAvrcpMediaRspInterface;
        mBDAddr = address;
    }

    /* initialize mediacontroller in order to communicate with media player. */
    private void onBrowseConnect() {
        boolean isError = false;
        MediaSession.Token token = null;
        try {
            /* get rootfolder uid from media player */
            if (mMediaId == null) {
                mMediaId = mMediaBrowser.getRoot();
                /*
                 * assuming that root folder uid will not change on uids changed
                 */
                mRootFolderUid = mMediaId;
                /* store root folder uid to stack */
                mPathStack.push(mMediaId);
            }

            if (!mMediaBrowser.isConnected()) {
                Log.e(TAG, "setBrowsedPlayer: " + mPackageName + "not connected");
            } else if ((token = mMediaBrowser.getSessionToken()) == null) {
                Log.e(TAG, "setBrowsedPlayer: " + mPackageName + "no Session token");
            } else {
                mMediaController = MediaController.wrap(
                    new android.media.session.MediaController(mContext, token));
                /* get root folder items */
                mMediaBrowser.subscribe(mRootFolderUid, folderItemsCb);
                return;
            }
        } catch (NullPointerException ex) {
            Log.e(TAG, "setBrowsedPlayer : Null pointer during init");
            ex.printStackTrace();
        }

        mMediaInterface.setBrowsedPlayerRsp(
                mBDAddr, AvrcpConstants.RSP_INTERNAL_ERR, (byte) 0x00, 0, null);
    }

    public void setBrowsed(String packageName, String cls) {
        mPackageName = packageName;
        mClassName = cls;
        /* cleanup variables from previous browsed calls */
        mFolderItems = null;
        mMediaId = null;
        mRootFolderUid = null;
        /*
         * create stack to store the navigation trail (current folder ID). This
         * will be required while navigating up the folder
         */
        mPathStack = new Stack<String>();
        /* Bind to MediaBrowseService of MediaPlayer */
        mMediaBrowser = new MediaBrowser(mContext, new ComponentName(mPackageName, mClassName),
                browseMediaConnectionCallback, null);
        mMediaBrowser.connect();
    }

    /* called when connection to media player is closed */
    public void cleanup() {
        if (DEBUG) Log.d(TAG, "cleanup");

        if (mConnState != DISCONNECTED) {
            mMediaBrowser.disconnect();
        }

        mHmap = null;
        mMediaController = null;
        mMediaBrowser = null;
        mPathStack = null;
    }

    public boolean isPlayerConnected() {
        if (mMediaBrowser == null) {
            if (DEBUG) Log.d(TAG, "isPlayerConnected: mMediaBrowser = null!");
            return false;
        }

        return mMediaBrowser.isConnected();
    }

    /* returns number of items in new path as reponse */
    public void changePath(byte[] folderUid, byte direction) {
        if (DEBUG) Log.d(TAG, "changePath.direction = " + direction);
        String newPath = "";

        if (isPlayerConnected() == false) {
            Log.w(TAG, "changePath: disconnected from player service, sending internal error");
            mMediaInterface.changePathRsp(mBDAddr, AvrcpConstants.RSP_INTERNAL_ERR, 0);
            return;
        }

        if (mMediaBrowser == null) {
            Log.e(TAG, "Media browser is null, sending internal error");
            mMediaInterface.changePathRsp(mBDAddr, AvrcpConstants.RSP_INTERNAL_ERR, 0);
            return;
        }

        /* check direction and change the path */
        if (direction == AvrcpConstants.DIR_DOWN) { /* move down */
            if ((newPath = byteToString(folderUid)) == null) {
                Log.e(TAG, "Could not get media item from folder Uid, sending err response");
                mMediaInterface.changePathRsp(mBDAddr, AvrcpConstants.RSP_INV_ITEM, 0);
            } else if (isBrowsableFolderDn(newPath) == false) {
                /* new path is not browsable */
                Log.e(TAG, "ItemUid received from changePath cmd is not browsable");
                mMediaInterface.changePathRsp(mBDAddr, AvrcpConstants.RSP_INV_DIRECTORY, 0);
            } else if (mPathStack.peek().equals(newPath) == true) {
                /* new_folder is same as current folder */
                Log.e(TAG, "new_folder is same as current folder, Invalid direction!");
                mMediaInterface.changePathRsp(mBDAddr, AvrcpConstants.RSP_INV_DIRN, 0);
            } else {
                mMediaBrowser.subscribe(newPath, folderItemsCb);
                /* assume that call is success and update stack with new folder path */
                mPathStack.push(newPath);
            }
        } else if (direction == AvrcpConstants.DIR_UP) { /* move up */
            if (isBrowsableFolderUp() == false) {
                /* Already on the root, cannot allow up: PTS: test case TC_TG_MCN_CB_BI_02_C
                 * This is required, otherwise some CT will keep on sending change path up
                 * until they receive error */
                Log.w(TAG, "Cannot go up from now, already in the root, Invalid direction!");
                mMediaInterface.changePathRsp(mBDAddr, AvrcpConstants.RSP_INV_DIRN, 0);
            } else {
                /* move folder up */
                mPathStack.pop();
                newPath = mPathStack.peek();
                mMediaBrowser.subscribe(newPath, folderItemsCb);
            }
        } else { /* invalid direction */
            Log.w(TAG, "changePath : Invalid direction " + direction);
            mMediaInterface.changePathRsp(mBDAddr, AvrcpConstants.RSP_INV_DIRN, 0);
        }
    }

    public void getItemAttr(AvrcpCmd.ItemAttrCmd itemAttr) {
        String mediaID;
        if (DEBUG) Log.d(TAG, "getItemAttr");

        /* check if uid is valid by doing a lookup in hashmap */
        mediaID = byteToString(itemAttr.mUid);
        if (mediaID == null) {
            Log.e(TAG, "uid is invalid");
            mMediaInterface.getItemAttrRsp(mBDAddr, AvrcpConstants.RSP_INV_ITEM, null);
            return;
        }

        /* check scope */
        if (itemAttr.mScope != AvrcpConstants.BTRC_SCOPE_FILE_SYSTEM) {
            Log.e(TAG, "invalid scope");
            mMediaInterface.getItemAttrRsp(mBDAddr, AvrcpConstants.RSP_INV_SCOPE, null);
            return;
        }

        if (mMediaBrowser == null) {
            Log.e(TAG, "mMediaBrowser is null");
            mMediaInterface.getItemAttrRsp(mBDAddr, AvrcpConstants.RSP_INTERNAL_ERR, null);
            return;
        }

        /* Subscribe to the parent to list items and retrieve the right one */
        mMediaBrowser.subscribe(mPathStack.peek(), new ItemAttribSubscriber(itemAttr, mediaID));
    }

    public void getTotalNumOfItems(byte scope) {
        if (DEBUG) Log.d(TAG, "getTotalNumOfItems scope = " + scope);
        if (scope != AvrcpConstants.BTRC_SCOPE_FILE_SYSTEM) {
            Log.e(TAG, "getTotalNumOfItems error" + scope);
            mMediaInterface.getTotalNumOfItemsRsp(mBDAddr, AvrcpConstants.RSP_INV_SCOPE, 0, 0);
            return;
        }

        if (mFolderItems == null) {
            Log.e(TAG, "mFolderItems is null, sending internal error");
            /* folderitems were not fetched during change path */
            mMediaInterface.getTotalNumOfItemsRsp(mBDAddr, AvrcpConstants.RSP_INTERNAL_ERR, 0, 0);
            return;
        }

        /* find num items using size of already cached folder items */
        mMediaInterface.getTotalNumOfItemsRsp(
                mBDAddr, AvrcpConstants.RSP_NO_ERROR, 0, mFolderItems.size());
    }

    public void getFolderItemsVFS(AvrcpCmd.FolderItemsCmd reqObj) {
        if (!isPlayerConnected()) {
            Log.e(TAG, "unable to connect to media player, sending internal error");
            /* unable to connect to media player. Send error response to remote device */
            mMediaInterface.folderItemsRsp(mBDAddr, AvrcpConstants.RSP_INTERNAL_ERR, null);
            return;
        }

        if (DEBUG) Log.d(TAG, "getFolderItemsVFS");
        mFolderItemsReqObj = reqObj;

        if (mFolderItems == null) {
            /* Failed to fetch folder items from media player. Send error to remote device */
            Log.e(TAG, "Failed to fetch folder items during getFolderItemsVFS");
            mMediaInterface.folderItemsRsp(mBDAddr, AvrcpConstants.RSP_INTERNAL_ERR, null);
            return;
        }

        /* Filter attributes based on the request and send response to remote device */
        getFolderItemsFilterAttr(mBDAddr, reqObj, mFolderItems,
                AvrcpConstants.BTRC_SCOPE_FILE_SYSTEM, mFolderItemsReqObj.mStartItem,
                mFolderItemsReqObj.mEndItem);
    }

    /* Instructs media player to play particular media item */
    public void playItem(byte[] uid, byte scope) {
        String folderUid;

        if (isPlayerConnected()) {
            /* check if uid is valid */
            if ((folderUid = byteToString(uid)) == null) {
                Log.e(TAG, "uid is invalid!");
                mMediaInterface.playItemRsp(mBDAddr, AvrcpConstants.RSP_INV_ITEM);
                return;
            }

            if (mMediaController != null) {
                MediaController.TransportControls mediaControllerCntrl =
                        mMediaController.getTransportControls();
                if (DEBUG) Log.d(TAG, "Sending playID: " + folderUid);

                if (scope == AvrcpConstants.BTRC_SCOPE_FILE_SYSTEM) {
                    mediaControllerCntrl.playFromMediaId(folderUid, null);
                    mMediaInterface.playItemRsp(mBDAddr, AvrcpConstants.RSP_NO_ERROR);
                } else {
                    Log.e(TAG, "playItem received for invalid scope!");
                    mMediaInterface.playItemRsp(mBDAddr, AvrcpConstants.RSP_INV_SCOPE);
                }
            } else {
                Log.e(TAG, "mediaController is null");
                mMediaInterface.playItemRsp(mBDAddr, AvrcpConstants.RSP_INTERNAL_ERR);
            }
        } else {
            Log.e(TAG, "playItem: Not connected to media player");
            mMediaInterface.playItemRsp(mBDAddr, AvrcpConstants.RSP_INTERNAL_ERR);
        }
    }

    /*
     * helper method to check if startItem and endItem index is with range of
     * MediaItem list. (Resultset containing all items in current path)
     */
    private List<MediaBrowser.MediaItem> checkIndexOutofBounds(
            byte[] bdaddr, List<MediaBrowser.MediaItem> children, long startItem, long endItem) {
        if (endItem > children.size()) endItem = children.size() - 1;
        if (startItem >= Integer.MAX_VALUE) startItem = Integer.MAX_VALUE;
        try {
            List<MediaBrowser.MediaItem> childrenSubList =
                    children.subList((int) startItem, (int) endItem + 1);
            if (childrenSubList.isEmpty()) {
                Log.i(TAG, "childrenSubList is empty.");
                throw new IndexOutOfBoundsException();
            }
            return childrenSubList;
        } catch (IndexOutOfBoundsException ex) {
            Log.w(TAG, "Index out of bounds start item ="+ startItem + " end item = "+
                    Math.min(children.size(), endItem + 1));
            return null;
        } catch (IllegalArgumentException ex) {
            Log.i(TAG, "Index out of bounds start item =" + startItem + " > size");
            return null;
        }
    }


    /*
     * helper method to filter required attibutes before sending GetFolderItems response
     */
    public void getFolderItemsFilterAttr(byte[] bdaddr, AvrcpCmd.FolderItemsCmd mFolderItemsReqObj,
            List<MediaBrowser.MediaItem> children, byte scope, long startItem, long endItem) {
        if (DEBUG)
            Log.d(TAG,
                    "getFolderItemsFilterAttr: startItem =" + startItem + ", endItem = " + endItem);

        List<MediaBrowser.MediaItem> result_items = new ArrayList<MediaBrowser.MediaItem>();

        if (children == null) {
            Log.e(TAG, "Error: children are null in getFolderItemsFilterAttr");
            mMediaInterface.folderItemsRsp(bdaddr, AvrcpConstants.RSP_INV_RANGE, null);
            return;
        }

        /* check for index out of bound errors */
        result_items = checkIndexOutofBounds(bdaddr, children, startItem, endItem);
        if (result_items == null) {
            Log.w(TAG, "result_items is null.");
            mMediaInterface.folderItemsRsp(bdaddr, AvrcpConstants.RSP_INV_RANGE, null);
            return;
        }
        FolderItemsData folderDataNative = new FolderItemsData(result_items.size());

        /* variables to temperorily add attrs */
        ArrayList<String> attrArray = new ArrayList<String>();
        ArrayList<Integer> attrId = new ArrayList<Integer>();

        for (int itemIndex = 0; itemIndex < result_items.size(); itemIndex++) {
            /* item type. Needs to be set by media player */
            MediaBrowser.MediaItem item = result_items.get(itemIndex);
            int flags = item.getFlags();
            if ((flags & MediaBrowser.MediaItem.FLAG_BROWSABLE) != 0) {
                folderDataNative.mItemTypes[itemIndex] = AvrcpConstants.BTRC_ITEM_FOLDER;
            } else {
                folderDataNative.mItemTypes[itemIndex] = AvrcpConstants.BTRC_ITEM_MEDIA;
            }

            /* set playable */
            if ((flags & MediaBrowser.MediaItem.FLAG_PLAYABLE) != 0) {
                folderDataNative.mPlayable[itemIndex] = AvrcpConstants.ITEM_PLAYABLE;
            } else {
                folderDataNative.mPlayable[itemIndex] = AvrcpConstants.ITEM_NOT_PLAYABLE;
            }
            /* set uid for current item */
            byte[] uid = stringToByte(item.getDescription().getMediaId());
            for (int idx = 0; idx < AvrcpConstants.UID_SIZE; idx++) {
                folderDataNative.mItemUid[itemIndex * AvrcpConstants.UID_SIZE + idx] = uid[idx];
            }

            /* Set display name for current item */
            folderDataNative.mDisplayNames[itemIndex] =
                    getAttrValue(AvrcpConstants.ATTRID_TITLE, item);

            int maxAttributesRequested = 0;
            boolean isAllAttribRequested = false;
            /* check if remote requested for attributes */
            if (mFolderItemsReqObj.mNumAttr != AvrcpConstants.NUM_ATTR_NONE) {
                int attrCnt = 0;

                /* add requested attr ids to a temp array */
                if (mFolderItemsReqObj.mNumAttr == AvrcpConstants.NUM_ATTR_ALL) {
                    isAllAttribRequested = true;
                    maxAttributesRequested = AvrcpConstants.MAX_NUM_ATTR;
                } else {
                    /* get only the requested attribute ids from the request */
                    maxAttributesRequested = mFolderItemsReqObj.mNumAttr;
                }

                /* lookup and copy values of attributes for ids requested above */
                for (int idx = 0; idx < maxAttributesRequested; idx++) {
                    /* check if media player provided requested attributes */
                    String value = null;

                    int attribId = isAllAttribRequested ? (idx + 1) :
                            mFolderItemsReqObj.mAttrIDs[idx];
                    value = getAttrValue(attribId, result_items.get(itemIndex));
                    if (value != null) {
                        attrArray.add(value);
                        attrId.add(attribId);
                        attrCnt++;
                    }
                }
                /* add num attr actually received from media player for a particular item */
                folderDataNative.mAttributesNum[itemIndex] = attrCnt;
            }
        }

        /* copy filtered attr ids and attr values to response parameters */
        if (attrId.size() > 0) {
            folderDataNative.mAttrIds = new int[attrId.size()];
            for (int attrIndex = 0; attrIndex < attrId.size(); attrIndex++)
                folderDataNative.mAttrIds[attrIndex] = attrId.get(attrIndex);
            folderDataNative.mAttrValues = attrArray.toArray(new String[attrArray.size()]);
        }

        /* create rsp object and send response to remote device */
        FolderItemsRsp rspObj = new FolderItemsRsp(AvrcpConstants.RSP_NO_ERROR, Avrcp.sUIDCounter,
                scope, folderDataNative.mNumItems, folderDataNative.mFolderTypes,
                folderDataNative.mPlayable, folderDataNative.mItemTypes, folderDataNative.mItemUid,
                folderDataNative.mDisplayNames, folderDataNative.mAttributesNum,
                folderDataNative.mAttrIds, folderDataNative.mAttrValues);
        mMediaInterface.folderItemsRsp(bdaddr, AvrcpConstants.RSP_NO_ERROR, rspObj);
    }

    public static String getAttrValue(int attr, MediaBrowser.MediaItem item) {
        String attrValue = null;
        try {
            MediaDescription desc = item.getDescription();
            Bundle extras = desc.getExtras();
            switch (attr) {
                /* Title is mandatory attribute */
                case AvrcpConstants.ATTRID_TITLE:
                    attrValue = desc.getTitle().toString();
                    break;

                case AvrcpConstants.ATTRID_ARTIST:
                    attrValue = extras.getString(MediaMetadata.METADATA_KEY_ARTIST);
                    break;

                case AvrcpConstants.ATTRID_ALBUM:
                    attrValue = extras.getString(MediaMetadata.METADATA_KEY_ALBUM);
                    break;

                case AvrcpConstants.ATTRID_TRACK_NUM:
                    attrValue = extras.getString(MediaMetadata.METADATA_KEY_TRACK_NUMBER);
                    break;

                case AvrcpConstants.ATTRID_NUM_TRACKS:
                    attrValue = extras.getString(MediaMetadata.METADATA_KEY_NUM_TRACKS);
                    break;

                case AvrcpConstants.ATTRID_GENRE:
                    attrValue = extras.getString(MediaMetadata.METADATA_KEY_GENRE);

                case AvrcpConstants.ATTRID_PLAY_TIME:
                    attrValue = extras.getString(MediaMetadata.METADATA_KEY_DURATION);

                case AvrcpConstants.ATTRID_COVER_ART:
                    Log.e(TAG, "getAttrValue: Cover art attribute not supported");
                    return null;

                default:
                    Log.e(TAG, "getAttrValue: Unknown attribute ID requested: " + attr);
                    return null;
            }
        } catch (NullPointerException ex) {
            Log.w(TAG, "getAttrValue: attr id not found in result");
            /* checking if attribute is title, then it is mandatory and cannot send null */
            if (attr == AvrcpConstants.ATTRID_TITLE) {
                attrValue = "<Unknown Title>";
            } else {
                return null;
            }
        }
        if (DEBUG) Log.d(TAG, "getAttrValue: attrvalue = " + attrValue + "attr id:" + attr);
        return attrValue;
    }


    public String getPackageName() {
        return mPackageName;
    }

    /* Helper methods */

    /* check if item is browsable Down*/
    private boolean isBrowsableFolderDn(String uid) {
        for (MediaBrowser.MediaItem item : mFolderItems) {
            if (item.getMediaId().equals(uid) &&
                ((item.getFlags() & MediaBrowser.MediaItem.FLAG_BROWSABLE) ==
                    MediaBrowser.MediaItem.FLAG_BROWSABLE))
                return true;
        }
        return false;
    }

    /* check if browsable Up*/
    private boolean isBrowsableFolderUp() {
        if (mPathStack.peek().equals(mRootFolderUid)) {
            /* Already on the root, cannot go up */
            return false;
        }
        return true;
    }

    /* convert uid to mediaId */
    private String byteToString(byte[] byteArray) {
        int uid = new BigInteger(byteArray).intValue();
        String mediaId = mHmap.get(uid);
        return mediaId;
    }

    /* convert mediaId to uid */
    private byte[] stringToByte(String mediaId) {
        /* check if this mediaId already exists in hashmap */
        if (!mHmap.containsValue(mediaId)) { /* add to hashmap */
            // Offset by one as uid 0 is reserved
            int uid = mHmap.size() + 1;
            mHmap.put(uid, mediaId);
            return intToByteArray(uid);
        } else { /* search key for give mediaId */
            for (int uid : mHmap.keySet()) {
                if (mHmap.get(uid).equals(mediaId)) {
                    return intToByteArray(uid);
                }
            }
        }
        return null;
    }

    /* converts queue item received from getQueue call, to MediaItem used by FilterAttr method */
    private List<MediaBrowser.MediaItem> queueItem2MediaItem(
            List<MediaSession.QueueItem> tempItems) {

        List<MediaBrowser.MediaItem> tempMedia = new ArrayList<MediaBrowser.MediaItem>();
        for (int itemCount = 0; itemCount < tempItems.size(); itemCount++) {
            MediaDescription.Builder build = new MediaDescription.Builder();
            build.setMediaId(Long.toString(tempItems.get(itemCount).getQueueId()));
            build.setTitle(tempItems.get(itemCount).getDescription().getTitle());
            build.setExtras(tempItems.get(itemCount).getDescription().getExtras());
            MediaDescription des = build.build();
            MediaItem item = new MediaItem((des), MediaItem.FLAG_PLAYABLE);
            tempMedia.add(item);
        }
        return tempMedia;
    }

    /* convert integer to byte array of size 8 bytes */
    public byte[] intToByteArray(int value) {
        int index = 0;
        byte[] encodedValue = new byte[AvrcpConstants.UID_SIZE];

        encodedValue[index++] = (byte)0x00;
        encodedValue[index++] = (byte)0x00;
        encodedValue[index++] = (byte)0x00;
        encodedValue[index++] = (byte)0x00;
        encodedValue[index++] = (byte)(value >> 24);
        encodedValue[index++] = (byte)(value >> 16);
        encodedValue[index++] = (byte)(value >> 8);
        encodedValue[index++] = (byte)value;

        return encodedValue;
    }
}
