/*
 * 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.BluetoothDevice;
import android.media.MediaDescription;
import android.media.browse.MediaBrowser;
import android.media.browse.MediaBrowser.MediaItem;
import android.os.Bundle;
import android.util.Log;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;

// Browsing hierarchy.
// Root:
//      Player1:
//        Now_Playing:
//          MediaItem1
//          MediaItem2
//        Folder1
//        Folder2
//        ....
//      Player2
//      ....
public class BrowseTree {
    private static final String TAG = "BrowseTree";
    private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
    private static final boolean VDBG = Log.isLoggable(TAG, Log.VERBOSE);

    public static final String ROOT = "__ROOT__";
    public static final String UP = "__UP__";
    public static final String NOW_PLAYING_PREFIX = "NOW_PLAYING";
    public static final String PLAYER_PREFIX = "PLAYER";

    // Static instance of Folder ID <-> Folder Instance (for navigation purposes)
    private final HashMap<String, BrowseNode> mBrowseMap = new HashMap<String, BrowseNode>();
    private BrowseNode mCurrentBrowseNode;
    private BrowseNode mCurrentBrowsedPlayer;
    private BrowseNode mCurrentAddressedPlayer;
    private int mDepth = 0;
    final BrowseNode mRootNode;
    final BrowseNode mNavigateUpNode;
    final BrowseNode mNowPlayingNode;

    BrowseTree(BluetoothDevice device) {
        if (device == null) {
            mRootNode = new BrowseNode(new MediaItem(new MediaDescription.Builder()
                    .setMediaId(ROOT).setTitle(ROOT).build(), MediaItem.FLAG_BROWSABLE));
            mRootNode.setCached(true);
        } else {
            mRootNode = new BrowseNode(new MediaItem(new MediaDescription.Builder()
                    .setMediaId(ROOT + device.getAddress().toString()).setTitle(
                            device.getName()).build(), MediaItem.FLAG_BROWSABLE));
            mRootNode.mDevice = device;

        }
        mRootNode.mBrowseScope = AvrcpControllerService.BROWSE_SCOPE_PLAYER_LIST;
        mRootNode.setExpectedChildren(255);

        mNavigateUpNode = new BrowseNode(new MediaItem(new MediaDescription.Builder()
                .setMediaId(UP).setTitle(UP).build(),
                MediaItem.FLAG_BROWSABLE));

        mNowPlayingNode = new BrowseNode(new MediaItem(new MediaDescription.Builder()
                .setMediaId(NOW_PLAYING_PREFIX)
                .setTitle(NOW_PLAYING_PREFIX).build(), MediaItem.FLAG_BROWSABLE));
        mNowPlayingNode.mBrowseScope = AvrcpControllerService.BROWSE_SCOPE_NOW_PLAYING;
        mNowPlayingNode.setExpectedChildren(255);
        mBrowseMap.put(ROOT, mRootNode);
        mBrowseMap.put(NOW_PLAYING_PREFIX, mNowPlayingNode);

        mCurrentBrowseNode = mRootNode;
    }

    public void clear() {
        // Clearing the map should garbage collect everything.
        mBrowseMap.clear();
    }

    void onConnected(BluetoothDevice device) {
        BrowseNode browseNode = new BrowseNode(device);
        mRootNode.addChild(browseNode);
    }

    BrowseNode getTrackFromNowPlayingList(int trackNumber) {
        return mNowPlayingNode.getChild(trackNumber);
    }

    // Each node of the tree is represented by Folder ID, Folder Name and the children.
    class BrowseNode {
        // MediaItem to store the media related details.
        MediaItem mItem;

        BluetoothDevice mDevice;
        long mBluetoothId;

        // Type of this browse node.
        // Since Media APIs do not define the player separately we define that
        // distinction here.
        boolean mIsPlayer = false;

        // If this folder is currently cached, can be useful to return the contents
        // without doing another fetch.
        boolean mCached = false;

        byte mBrowseScope = AvrcpControllerService.BROWSE_SCOPE_VFS;

        // List of children.
        private BrowseNode mParent;
        private final List<BrowseNode> mChildren = new ArrayList<BrowseNode>();
        private int mExpectedChildrenCount;

        BrowseNode(MediaItem item) {
            mItem = item;
            Bundle extras = mItem.getDescription().getExtras();
            if (extras != null) {
                mBluetoothId = extras.getLong(AvrcpControllerService.MEDIA_ITEM_UID_KEY);
            }
        }

        BrowseNode(AvrcpPlayer player) {
            mIsPlayer = true;

            // Transform the player into a item.
            MediaDescription.Builder mdb = new MediaDescription.Builder();
            String playerKey = PLAYER_PREFIX + player.getId();
            mBluetoothId = player.getId();

            mdb.setMediaId(UUID.randomUUID().toString());
            mdb.setTitle(player.getName());
            int mediaItemFlags = player.supportsFeature(AvrcpPlayer.FEATURE_BROWSING)
                    ? MediaBrowser.MediaItem.FLAG_BROWSABLE : 0;
            mItem = new MediaBrowser.MediaItem(mdb.build(), mediaItemFlags);
        }

        BrowseNode(BluetoothDevice device) {
            boolean mIsPlayer = true;
            mDevice = device;
            MediaDescription.Builder mdb = new MediaDescription.Builder();
            String playerKey = PLAYER_PREFIX + device.getAddress().toString();
            mdb.setMediaId(playerKey);
            mdb.setTitle(device.getName());
            int mediaItemFlags = MediaBrowser.MediaItem.FLAG_BROWSABLE;
            mItem = new MediaBrowser.MediaItem(mdb.build(), mediaItemFlags);
        }

        private BrowseNode(String name) {
            MediaDescription.Builder mdb = new MediaDescription.Builder();
            mdb.setMediaId(name);
            mdb.setTitle(name);
            mItem = new MediaBrowser.MediaItem(mdb.build(), MediaBrowser.MediaItem.FLAG_BROWSABLE);
        }

        synchronized void setExpectedChildren(int count) {
            mExpectedChildrenCount = count;
        }

        synchronized int getExpectedChildren() {
            return mExpectedChildrenCount;
        }

        synchronized <E> int addChildren(List<E> newChildren) {
            for (E child : newChildren) {
                BrowseNode currentNode = null;
                if (child instanceof MediaItem) {
                    currentNode = new BrowseNode((MediaItem) child);
                } else if (child instanceof AvrcpPlayer) {
                    currentNode = new BrowseNode((AvrcpPlayer) child);
                }
                addChild(currentNode);
            }
            return newChildren.size();
        }

        synchronized boolean addChild(BrowseNode node) {
            if (node != null) {
                node.mParent = this;
                if (this.mBrowseScope == AvrcpControllerService.BROWSE_SCOPE_NOW_PLAYING) {
                    node.mBrowseScope = this.mBrowseScope;
                }
                if (node.mDevice == null) {
                    node.mDevice = this.mDevice;
                }
                mChildren.add(node);
                mBrowseMap.put(node.getID(), node);
                return true;
            }
            return false;
        }

        synchronized void removeChild(BrowseNode node) {
            mChildren.remove(node);
            mBrowseMap.remove(node.getID());
        }

        synchronized int getChildrenCount() {
            return mChildren.size();
        }

        synchronized List<BrowseNode> getChildren() {
            return mChildren;
        }

        synchronized BrowseNode getChild(int index) {
            if (index < 0 || index >= mChildren.size()) {
                return null;
            }
            return mChildren.get(index);
        }

        synchronized BrowseNode getParent() {
            return mParent;
        }

        synchronized List<MediaItem> getContents() {
            if (mChildren.size() > 0 || mCached) {
                List<MediaItem> contents = new ArrayList<MediaItem>(mChildren.size());
                for (BrowseNode child : mChildren) {
                    contents.add(child.getMediaItem());
                }
                return contents;
            }
            return null;
        }

        synchronized boolean isChild(BrowseNode node) {
            return mChildren.contains(node);
        }

        synchronized boolean isCached() {
            return mCached;
        }

        synchronized boolean isBrowsable() {
            return mItem.isBrowsable();
        }

        synchronized void setCached(boolean cached) {
            if (DBG) Log.d(TAG, "Set Cache" + cached + "Node" + toString());
            mCached = cached;
            if (!cached) {
                for (BrowseNode child : mChildren) {
                    mBrowseMap.remove(child.getID());
                }
                mChildren.clear();
            }
        }

        // Fetch the Unique UID for this item, this is unique across all elements in the tree.
        synchronized String getID() {
            return mItem.getDescription().getMediaId();
        }

        // Get the BT Player ID associated with this node.
        synchronized int getPlayerID() {
            return Integer.parseInt(getID().replace(PLAYER_PREFIX, ""));
        }

        synchronized byte getScope() {
            return mBrowseScope;
        }

        // Fetch the Folder UID that can be used to fetch folder listing via bluetooth.
        // This may not be unique hence this combined with direction will define the
        // browsing here.
        synchronized String getFolderUID() {
            return getID();
        }

        synchronized long getBluetoothID() {
            return mBluetoothId;
        }

        synchronized MediaItem getMediaItem() {
            return mItem;
        }

        synchronized boolean isPlayer() {
            return mIsPlayer;
        }

        synchronized boolean isNowPlaying() {
            return getID().startsWith(NOW_PLAYING_PREFIX);
        }

        @Override
        public boolean equals(Object other) {
            if (!(other instanceof BrowseNode)) {
                return false;
            }
            BrowseNode otherNode = (BrowseNode) other;
            return getID().equals(otherNode.getID());
        }

        @Override
        public synchronized String toString() {
            if (VDBG) {
                String serialized = "[ Name: " + mItem.getDescription().getTitle()
                        + " Scope:" + mBrowseScope + " expected Children: "
                        + mExpectedChildrenCount + "] ";
                for (BrowseNode node : mChildren) {
                    serialized += node.toString();
                }
                return serialized;
            } else {
                return "ID: " + getID();
            }
        }

        // Returns true if target is a descendant of this.
        synchronized boolean isDescendant(BrowseNode target) {
            return getEldestChild(this, target) == null ? false : true;
        }
    }

    synchronized BrowseNode findBrowseNodeByID(String parentID) {
        BrowseNode bn = mBrowseMap.get(parentID);
        if (bn == null) {
            Log.e(TAG, "folder " + parentID + " not found!");
            return null;
        }
        if (VDBG) {
            Log.d(TAG, "Size" + mBrowseMap.size());
        }
        return bn;
    }

    synchronized boolean setCurrentBrowsedFolder(String uid) {
        BrowseNode bn = mBrowseMap.get(uid);
        if (bn == null) {
            Log.e(TAG, "Setting an unknown browsed folder, ignoring bn " + uid);
            return false;
        }

        // Set the previous folder as not cached so that we fetch the contents again.
        if (!bn.equals(mCurrentBrowseNode)) {
            Log.d(TAG, "Set cache  " + bn + " curr " + mCurrentBrowseNode);
        }
        mCurrentBrowseNode = bn;
        return true;
    }

    synchronized BrowseNode getCurrentBrowsedFolder() {
        return mCurrentBrowseNode;
    }

    synchronized boolean setCurrentBrowsedPlayer(String uid, int items, int depth) {
        BrowseNode bn = mBrowseMap.get(uid);
        if (bn == null) {
            Log.e(TAG, "Setting an unknown browsed player, ignoring bn " + uid);
            return false;
        }
        mCurrentBrowsedPlayer = bn;
        mCurrentBrowseNode = mCurrentBrowsedPlayer;
        for (Integer level = 0; level < depth; level++) {
            BrowseNode dummyNode = new BrowseNode(level.toString());
            dummyNode.mParent = mCurrentBrowseNode;
            dummyNode.mBrowseScope = AvrcpControllerService.BROWSE_SCOPE_VFS;
            mCurrentBrowseNode = dummyNode;
        }
        mCurrentBrowseNode.setExpectedChildren(items);
        mDepth = depth;
        return true;
    }

    synchronized BrowseNode getCurrentBrowsedPlayer() {
        return mCurrentBrowsedPlayer;
    }

    synchronized boolean setCurrentAddressedPlayer(String uid) {
        BrowseNode bn = mBrowseMap.get(uid);
        if (bn == null) {
            if (DBG) Log.d(TAG, "Setting an unknown addressed player, ignoring bn " + uid);
            mRootNode.setCached(false);
            mRootNode.mChildren.add(mNowPlayingNode);
            mBrowseMap.put(NOW_PLAYING_PREFIX, mNowPlayingNode);
            return false;
        }
        mCurrentAddressedPlayer = bn;
        return true;
    }

    synchronized BrowseNode getCurrentAddressedPlayer() {
        return mCurrentAddressedPlayer;
    }

    @Override
    public String toString() {
        String serialized = "Size: " + mBrowseMap.size();
        if (VDBG) {
            serialized += mRootNode.toString();
        }
        return serialized;
    }

    // Calculates the path to target node.
    // Returns: UP node to go up
    // Returns: target node if there
    // Returns: named node to go down
    // Returns: null node if unknown
    BrowseNode getNextStepToFolder(BrowseNode target) {
        if (target == null) {
            return null;
        } else if (target.equals(mCurrentBrowseNode)
                || target.equals(mNowPlayingNode)
                || target.equals(mRootNode)) {
            return target;
        } else if (target.isPlayer()) {
            if (mDepth > 0) {
                mDepth--;
                return mNavigateUpNode;
            } else {
                return target;
            }
        } else if (mBrowseMap.get(target.getID()) == null) {
            return null;
        } else {
            BrowseNode nextChild = getEldestChild(mCurrentBrowseNode, target);
            if (nextChild == null) {
                return mNavigateUpNode;
            } else {
                return nextChild;
            }
        }
    }

    static BrowseNode getEldestChild(BrowseNode ancestor, BrowseNode target) {
        // ancestor is an ancestor of target
        BrowseNode descendant = target;
        if (DBG) {
            Log.d(TAG, "NAVIGATING ancestor" + ancestor.toString() + "Target"
                    + target.toString());
        }
        while (!ancestor.equals(descendant.mParent)) {
            descendant = descendant.mParent;
            if (descendant == null) {
                return null;
            }
        }
        if (DBG) Log.d(TAG, "NAVIGATING Descendant" + descendant.toString());
        return descendant;
    }
}
