/*
 * Copyright (C) 2012 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 android.net.wifi.p2p.nsd;

import android.compat.annotation.UnsupportedAppUsage;
import android.net.nsd.DnsSdTxtRecord;
import android.os.Build;
import android.text.TextUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

/**
 * A class for storing Bonjour service information that is advertised
 * over a Wi-Fi peer-to-peer setup.
 *
 * {@see android.net.wifi.p2p.WifiP2pManager#addLocalService}
 * {@see android.net.wifi.p2p.WifiP2pManager#removeLocalService}
 * {@see WifiP2pServiceInfo}
 * {@see WifiP2pUpnpServiceInfo}
 */
public class WifiP2pDnsSdServiceInfo extends WifiP2pServiceInfo {

    /**
     * Bonjour version 1.
     * @hide
     */
    public static final int VERSION_1 = 0x01;

    /**
     * Pointer record.
     * @hide
     */
    public static final int DNS_TYPE_PTR = 12;

    /**
     * Text record.
     * @hide
     */
    public static final int DNS_TYPE_TXT = 16;

    /**
     * virtual memory packet.
     * see E.3 of the Wi-Fi Direct technical specification for the detail.<br>
     * Key: domain name Value: pointer address.<br>
     */
    private final static Map<String, String> sVmPacket;

    static {
        sVmPacket = new HashMap<String, String>();
        sVmPacket.put("_tcp.local.", "c00c");
        sVmPacket.put("local.", "c011");
        sVmPacket.put("_udp.local.", "c01c");
    }

    /**
     * This constructor is only used in newInstance().
     *
     * @param queryList
     */
    private WifiP2pDnsSdServiceInfo(List<String> queryList) {
        super(queryList);
    }

    /**
     * Create a Bonjour service information object.
     *
     * @param instanceName instance name.<br>
     *  e.g) "MyPrinter"
     * @param serviceType service type.<br>
     *  e.g) "_ipp._tcp"
     * @param txtMap TXT record with key/value pair in a map confirming to format defined at
     * http://files.dns-sd.org/draft-cheshire-dnsext-dns-sd.txt
     * @return Bonjour service information object
     */
    public static WifiP2pDnsSdServiceInfo newInstance(String instanceName,
            String serviceType, Map<String, String> txtMap) {
        if (TextUtils.isEmpty(instanceName) || TextUtils.isEmpty(serviceType)) {
            throw new IllegalArgumentException(
                    "instance name or service type cannot be empty");
        }

        DnsSdTxtRecord txtRecord = new DnsSdTxtRecord();
        if (txtMap != null) {
            for (String key : txtMap.keySet()) {
                txtRecord.set(key, txtMap.get(key));
            }
        }

        ArrayList<String> queries = new ArrayList<String>();
        queries.add(createPtrServiceQuery(instanceName, serviceType));
        queries.add(createTxtServiceQuery(instanceName, serviceType, txtRecord));

        return new WifiP2pDnsSdServiceInfo(queries);
    }

    /**
     * Create wpa_supplicant service query for PTR record.
     *
     * @param instanceName instance name.<br>
     *  e.g) "MyPrinter"
     * @param serviceType service type.<br>
     *  e.g) "_ipp._tcp"
     * @return wpa_supplicant service query.
     */
    private static String createPtrServiceQuery(String instanceName,
            String serviceType) {

        StringBuffer sb = new StringBuffer();
        sb.append("bonjour ");
        sb.append(createRequest(serviceType + ".local.", DNS_TYPE_PTR, VERSION_1));
        sb.append(" ");

        byte[] data = instanceName.getBytes();
        sb.append(String.format(Locale.US, "%02x", data.length));
        sb.append(WifiP2pServiceInfo.bin2HexStr(data));
        // This is the start point of this response.
        // Therefore, it indicates the request domain name.
        sb.append("c027");
        return sb.toString();
    }

    /**
     * Create wpa_supplicant service query for TXT record.
     *
     * @param instanceName instance name.<br>
     *  e.g) "MyPrinter"
     * @param serviceType service type.<br>
     *  e.g) "_ipp._tcp"
     * @param txtRecord TXT record.<br>
     * @return wpa_supplicant service query.
     */
    private static String createTxtServiceQuery(String instanceName,
            String serviceType,
            DnsSdTxtRecord txtRecord) {


        StringBuffer sb = new StringBuffer();
        sb.append("bonjour ");

        sb.append(createRequest((instanceName + "." + serviceType + ".local."),
                DNS_TYPE_TXT, VERSION_1));
        sb.append(" ");
        byte[] rawData = txtRecord.getRawData();
        if (rawData.length == 0) {
            sb.append("00");
        } else {
            sb.append(bin2HexStr(rawData));
        }
        return sb.toString();
    }

    /**
     * Create bonjour service discovery request.
     *
     * @param dnsName dns name
     * @param dnsType dns type
     * @param version version number
     * @hide
     */
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
    static String createRequest(String dnsName, int dnsType, int version) {
        StringBuffer sb = new StringBuffer();

        /*
         * The request format is as follows.
         * ________________________________________________
         * |  Encoded and Compressed dns name (variable)  |
         * ________________________________________________
         * |   Type (2)           | Version (1) |
         */
        if (dnsType == WifiP2pDnsSdServiceInfo.DNS_TYPE_TXT) {
            dnsName = dnsName.toLowerCase(Locale.ROOT); // TODO: is this right?
        }
        sb.append(compressDnsName(dnsName));
        sb.append(String.format(Locale.US, "%04x", dnsType));
        sb.append(String.format(Locale.US, "%02x", version));

        return sb.toString();
    }

    /**
     * Compress DNS data.
     *
     * see E.3 of the Wi-Fi Direct technical specification for the detail.
     *
     * @param dnsName dns name
     * @return compressed dns name
     */
    private static String compressDnsName(String dnsName) {
        StringBuffer sb = new StringBuffer();

        // The domain name is replaced with a pointer to a prior
        // occurrence of the same name in virtual memory packet.
        while (true) {
            String data = sVmPacket.get(dnsName);
            if (data != null) {
                sb.append(data);
                break;
            }
            int i = dnsName.indexOf('.');
            if (i == -1) {
                if (dnsName.length() > 0) {
                    sb.append(String.format(Locale.US, "%02x", dnsName.length()));
                    sb.append(WifiP2pServiceInfo.bin2HexStr(dnsName.getBytes()));
                }
                // for a sequence of labels ending in a zero octet
                sb.append("00");
                break;
            }

            String name = dnsName.substring(0, i);
            dnsName = dnsName.substring(i + 1);
            sb.append(String.format(Locale.US, "%02x", name.length()));
            sb.append(WifiP2pServiceInfo.bin2HexStr(name.getBytes()));
        }
        return sb.toString();
    }
}
