package org.fdroid.fdroid.localrepo.type;

import android.content.Context;
import android.support.annotation.Nullable;
import android.util.Log;

import org.fdroid.fdroid.FDroidApp;
import org.fdroid.fdroid.Preferences;
import org.fdroid.fdroid.Utils;
import org.fdroid.fdroid.localrepo.SwapService;

import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.HashMap;

import javax.jmdns.JmDNS;
import javax.jmdns.ServiceInfo;

/**
 * Sends a {@link SwapService#BONJOUR_STATE_CHANGE} broadcasts when starting, started or stopped.
 */
public class BonjourBroadcast extends SwapType {

    private static final String TAG = "BonjourBroadcast";

    private JmDNS jmdns;
    private ServiceInfo pairService;

    public BonjourBroadcast(Context context) {
        super(context);
    }

    @Override
    public void start() {
        Utils.debugLog(TAG, "Preparing to start Bonjour service.");
        sendBroadcast(SwapService.EXTRA_STARTING);

        InetAddress address = getDeviceAddress();
        if (address == null) {
            Log.e(TAG, "Starting Bonjour service, but couldn't ascertain IP address. Seems we are not connected to a network.");
            return;
        }

        /*
         * a ServiceInfo can only be registered with a single instance
         * of JmDNS, and there is only ever a single LocalHTTPD port to
         * advertise anyway.
         */
        if (pairService != null || jmdns != null) {
            clearCurrentMDNSService();
        }

        String repoName = Preferences.get().getLocalRepoName();
        HashMap<String, String> values = new HashMap<>();
        values.put("path", "/fdroid/repo");
        values.put("name", repoName);
        values.put("fingerprint", FDroidApp.repo.fingerprint);
        String type;
        if (Preferences.get().isLocalRepoHttpsEnabled()) {
            values.put("type", "fdroidrepos");
            type = "_https._tcp.local.";
        } else {
            values.put("type", "fdroidrepo");
            type = "_http._tcp.local.";
        }
        try {
            Utils.debugLog(TAG, "Starting bonjour service...");
            pairService = ServiceInfo.create(type, repoName, FDroidApp.port, 0, 0, values);
            jmdns = JmDNS.create(address);
            jmdns.registerService(pairService);
            setConnected(true);
            Utils.debugLog(TAG, "... Bounjour service started.");
        } catch (IOException e) {
            Log.e(TAG, "Error while registering jmdns service", e);
            setConnected(false);
        }
    }

    @Override
    public void stop() {
        Utils.debugLog(TAG, "Unregistering MDNS service...");
        clearCurrentMDNSService();
        setConnected(false);
    }

    private void clearCurrentMDNSService() {
        if (jmdns != null) {
            jmdns.unregisterAllServices();
            Utils.closeQuietly(jmdns);
            pairService = null;
            jmdns = null;
        }
    }

    @Override
    public String getBroadcastAction() {
        return SwapService.BONJOUR_STATE_CHANGE;
    }

    @Nullable
    private InetAddress getDeviceAddress() {
        if (FDroidApp.ipAddressString != null) {
            try {
                return InetAddress.getByName(FDroidApp.ipAddressString);
            } catch (UnknownHostException ignored) { }
        }

        return null;
    }

}
