/*
 * Copyright 2018 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.car.media.common.browse;

import android.annotation.NonNull;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.media.MediaBrowserCompat;

import androidx.lifecycle.LiveData;

import com.android.car.media.common.MediaItemMetadata;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * A LiveData that provides access the a MediaBrowser's children
 */

class BrowsedMediaItems extends LiveData<List<MediaItemMetadata>> {

    /**
     * Number of times we will retry obtaining the list of children of a certain node
     */
    private static final int CHILDREN_SUBSCRIPTION_RETRIES = 1;
    /**
     * Time between retries while trying to obtain the list of children of a certain node
     */
    private static final int CHILDREN_SUBSCRIPTION_RETRY_TIME_MS = 5000;

    /** Whether to send an error after the last timeout. The subscription stays active regardless.*/
    private static final boolean LAST_RETRY_TIMEOUT_SENDS_ERROR = false;

    private final MediaBrowserCompat mBrowser;
    private final String mParentId;
    private final Handler mHandler = new Handler();

    private ChildrenSubscription mSubscription;

    BrowsedMediaItems(@NonNull MediaBrowserCompat mediaBrowser, @NonNull String parentId) {
        mBrowser = mediaBrowser;
        mParentId = parentId;
    }

    @Override
    protected void onActive() {
        super.onActive();
        mSubscription = new ChildrenSubscription(mParentId);
        mSubscription.start(CHILDREN_SUBSCRIPTION_RETRIES, CHILDREN_SUBSCRIPTION_RETRY_TIME_MS);
    }

    @Override
    protected void onInactive() {
        super.onInactive();
        mSubscription.stop();
        mSubscription = null;
        mHandler.removeCallbacksAndMessages(null);
    }

    /**
     * {@link MediaBrowserCompat.SubscriptionCallback} wrapper used to overcome the lack of a
     * reliable method to obtain the initial list of children of a given node.
     * <p>
     * When some 3rd party apps go through configuration changes (i.e., in the case of user-switch),
     * they leave subscriptions in an intermediate state where neither {@link
     * MediaBrowserCompat.SubscriptionCallback#onChildrenLoaded(String, List)} nor {@link
     * MediaBrowserCompat.SubscriptionCallback#onError(String)} are invoked.
     * <p>
     * This wrapper works around this problem by retrying the subscription a given number of times
     * if no data is received after a certain amount of time. This process is started by calling
     * {@link #start(int, int)}, passing the number of retries and delay between them as
     * parameters.
     * TODO: remove all this code if it's indeed not needed anymore (using retry=1 to be sure).
     */
    private class ChildrenSubscription extends MediaBrowserCompat.SubscriptionCallback {
        private final String mItemId;

        private boolean mIsDataLoaded;
        private int mRetries;
        private int mRetryDelay;

        ChildrenSubscription(String itemId) {
            mItemId = itemId;
        }

        private Runnable mRetryRunnable = new Runnable() {
            @Override
            public void run() {
                if (!mIsDataLoaded) {
                    if (mRetries > 0) {
                        mRetries--;
                        mBrowser.unsubscribe(mItemId);
                        mBrowser.subscribe(mItemId, ChildrenSubscription.this);
                        mHandler.postDelayed(this, mRetryDelay);
                    } else if (LAST_RETRY_TIMEOUT_SENDS_ERROR) {
                        mIsDataLoaded = true;
                        setValue(null);
                    }
                }
            }
        };

        /**
         * Starts trying to obtain the list of children
         *
         * @param retries    number of times to retry. If children are not obtained in this time
         *                   then the LiveData's value will be set to {@code null}
         * @param retryDelay time between retries in milliseconds
         */
        void start(int retries, int retryDelay) {
            if (mIsDataLoaded) {
                mBrowser.subscribe(mItemId, this);
            } else {
                mRetries = retries;
                mRetryDelay = retryDelay;
                mHandler.post(mRetryRunnable);
            }
        }

        /**
         * Stops retrying
         */
        void stop() {
            mHandler.removeCallbacks(mRetryRunnable);
            mBrowser.unsubscribe(mItemId);
        }

        @Override
        public void onChildrenLoaded(@NonNull String parentId,
                @NonNull List<MediaBrowserCompat.MediaItem> children) {
            mHandler.removeCallbacks(mRetryRunnable);
            mIsDataLoaded = true;
            setValue(children.stream()
                    .filter(Objects::nonNull)
                    .map(MediaItemMetadata::new)
                    .collect(Collectors.toList()));
        }

        @Override
        public void onChildrenLoaded(@NonNull String parentId,
                @NonNull List<MediaBrowserCompat.MediaItem> children,
                @NonNull Bundle options) {
            onChildrenLoaded(parentId, children);
        }

        @Override
        public void onError(@NonNull String parentId) {
            mHandler.removeCallbacks(mRetryRunnable);
            mIsDataLoaded = true;
            setValue(null);
        }

        @Override
        public void onError(@NonNull String parentId, @NonNull Bundle options) {
            onError(parentId);
        }
    }
}
