/*
 * 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.printservice.recommendation.util;

import android.annotation.NonNull;
import android.net.nsd.NsdManager;
import android.net.nsd.NsdServiceInfo;
import android.util.ArrayMap;
import android.util.Log;

import java.util.ArrayList;

/**
 * Used to multiplex listening for NSD services. This is needed as only a limited amount of
 * {@link NsdManager.DiscoveryListener listeners} are allowed.
 */
public class DiscoveryListenerMultiplexer {
    private static final String LOG_TAG = "DiscoveryListenerMx";

    /** List of registered {@link DiscoveryListenerSet discovery sets}. */
    private static final @NonNull ArrayMap<String, DiscoveryListenerSet> sListeners =
            new ArrayMap<>();

    /**
     * Add a new {@link NsdManager.DiscoveryListener listener} for a {@code serviceType}.
     *
     * @param nsdManager  The {@link NsdManager NSD manager} to use
     * @param serviceType The service type to listen for
     * @param newListener the {@link NsdManager.DiscoveryListener listener} to add.
     */
    public static void addListener(@NonNull NsdManager nsdManager, @NonNull String serviceType,
            @NonNull NsdManager.DiscoveryListener newListener) {
        synchronized (sListeners) {
            DiscoveryListenerSet listenerSet = sListeners.get(serviceType);

            if (listenerSet == null) {
                ArrayList<NsdManager.DiscoveryListener> subListeners = new ArrayList<>(1);
                listenerSet = new DiscoveryListenerSet(subListeners,
                        new MultiListener(subListeners));

                sListeners.put(serviceType, listenerSet);
            }

            synchronized (listenerSet.subListeners) {
                if (listenerSet.subListeners.isEmpty()) {
                    nsdManager.discoverServices(serviceType, NsdManager.PROTOCOL_DNS_SD,
                            listenerSet.mainListener);
                }

                listenerSet.subListeners.add(newListener);
            }
        }
    }

    /**
     * Remove a previously added {@link NsdManager.DiscoveryListener listener}.
     *
     * @param nsdManager The {@link NsdManager NSD manager} to use
     * @param listener   The {@link NsdManager.DiscoveryListener listener} that was registered
     *
     * @return true iff the listener was removed
     */
    public static boolean removeListener(@NonNull NsdManager nsdManager,
            @NonNull NsdManager.DiscoveryListener listener) {
        boolean wasRemoved = false;

        synchronized (sListeners) {
            for (DiscoveryListenerSet listeners : sListeners.values()) {
                synchronized (listeners) {
                    wasRemoved = listeners.subListeners.remove(listener);

                    if (wasRemoved) {
                        if (listeners.subListeners.isEmpty()) {
                            nsdManager.stopServiceDiscovery(listeners.mainListener);
                        }

                        break;
                    }
                }
            }
        }

        return wasRemoved;
    }

    /** Private class holding all data for a service type */
    private static class DiscoveryListenerSet {
        /** The plugin's listeners */
        final @NonNull ArrayList<NsdManager.DiscoveryListener> subListeners;

        /** The listener registered with the NSD Manager */
        final @NonNull MultiListener mainListener;

        private DiscoveryListenerSet(ArrayList<NsdManager.DiscoveryListener> subListeners,
                MultiListener mainListener) {
            this.subListeners = subListeners;
            this.mainListener = mainListener;
        }
    }

    /**
     * A {@link NsdManager.DiscoveryListener} that calls a list of registered listeners when
     * a service is found or lost.
     */
    private static class MultiListener implements NsdManager.DiscoveryListener {
        private final @NonNull ArrayList<NsdManager.DiscoveryListener> mListeners;

        /**
         * Create a new multi listener.
         *
         * @param listeners The listeners to forward the calls.
         */
        public MultiListener(@NonNull ArrayList<NsdManager.DiscoveryListener> listeners) {
            mListeners = listeners;
        }

        @Override
        public void onStartDiscoveryFailed(String serviceType, int errorCode) {
            Log.w(LOG_TAG, "Failed to start network discovery for type " + serviceType + ": "
                    + errorCode);
        }

        @Override
        public void onStopDiscoveryFailed(String serviceType, int errorCode) {
            Log.w(LOG_TAG, "Failed to stop network discovery for type " + serviceType + ": "
                    + errorCode);
        }

        @Override
        public void onDiscoveryStarted(String serviceType) {
            // not implemented
        }

        @Override
        public void onDiscoveryStopped(String serviceType) {
            // not implemented
        }

        @Override
        public void onServiceFound(NsdServiceInfo serviceInfo) {
            synchronized (mListeners) {
                int numListeners = mListeners.size();
                for (int i = 0; i < numListeners; i++) {
                    NsdManager.DiscoveryListener listener = mListeners.get(i);

                    listener.onServiceFound(serviceInfo);
                }
            }
        }

        @Override
        public void onServiceLost(NsdServiceInfo serviceInfo) {
            synchronized (mListeners) {
                int numListeners = mListeners.size();
                for (int i = 0; i < numListeners; i++) {
                    NsdManager.DiscoveryListener listener = mListeners.get(i);

                    listener.onServiceLost(serviceInfo);
                }
            }
        }
    }
}
