/*
 * 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.net.wifi.p2p.WifiP2pDevice;
import android.os.Parcel;
import android.os.Parcelable;

import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * The class for a response of service discovery.
 *
 * @hide
 */
public class WifiP2pServiceResponse implements Parcelable {

    private static int MAX_BUF_SIZE = 1024;

    /**
     * Service type. It's defined in table63 in Wi-Fi Direct specification.
     */
    protected int mServiceType;

    /**
     * Status code of service discovery response.
     * It's defined in table65 in Wi-Fi Direct specification.
     * @see Status
     */
    protected int mStatus;

    /**
     * Service transaction ID.
     * This is a nonzero value used to match the service request/response TLVs.
     */
    protected int mTransId;

    /**
     * Source device.
     */
    protected WifiP2pDevice mDevice;

    /**
     * Service discovery response data based on the requested on
     * the service protocol type. The protocol format depends on the service type.
     */
    protected byte[] mData;


    /**
     * The status code of service discovery response.
     * Currently 4 status codes are defined and the status codes from  4 to 255
     * are reserved.
     *
     * See Wi-Fi Direct specification for the detail.
     */
    public static class Status {
        /** success */
        public static final int SUCCESS = 0;

        /** the service protocol type is not available */
        public static final int SERVICE_PROTOCOL_NOT_AVAILABLE = 1;

        /** the requested information is not available */
        public static final int REQUESTED_INFORMATION_NOT_AVAILABLE = 2;

        /** bad request */
        public static final int BAD_REQUEST = 3;

        /** @hide */
        public static String toString(int status) {
            switch(status) {
            case SUCCESS:
                return "SUCCESS";
            case SERVICE_PROTOCOL_NOT_AVAILABLE:
                return "SERVICE_PROTOCOL_NOT_AVAILABLE";
            case REQUESTED_INFORMATION_NOT_AVAILABLE:
                return "REQUESTED_INFORMATION_NOT_AVAILABLE";
            case BAD_REQUEST:
                return "BAD_REQUEST";
            default:
                return "UNKNOWN";
            }
        }

        /** not used */
        private Status() {}
    }

    /**
     * Hidden constructor. This is only used in framework.
     *
     * @param serviceType service discovery type.
     * @param status status code.
     * @param transId transaction id.
     * @param device source device.
     * @param data query data.
     */
    protected WifiP2pServiceResponse(int serviceType, int status, int transId,
            WifiP2pDevice device, byte[] data) {
        mServiceType = serviceType;
        mStatus = status;
        mTransId = transId;
        mDevice = device;
        mData = data;
    }

    /**
     * Return the service type of service discovery response.
     *
     * @return service discovery type.<br>
     * e.g) {@link WifiP2pServiceInfo#SERVICE_TYPE_BONJOUR}
     */
    public int getServiceType() {
        return mServiceType;
    }

    /**
     * Return the status code of service discovery response.
     *
     * @return status code.
     * @see Status
     */
    public int getStatus() {
        return mStatus;
    }

    /**
     * Return the transaction id of service discovery response.
     *
     * @return transaction id.
     * @hide
     */
    public int getTransactionId() {
        return mTransId;
    }

    /**
     * Return response data.
     *
     * <pre>Data format depends on service type
     *
     * @return a query or response data.
     */
    public byte[] getRawData() {
        return mData;
    }

    /**
     * Returns the source device of service discovery response.
     *
     * <pre>This is valid only when service discovery response.
     *
     * @return the source device of service discovery response.
     */
    public WifiP2pDevice getSrcDevice() {
        return mDevice;
    }

    /** @hide */
    public void setSrcDevice(WifiP2pDevice dev) {
        if (dev == null) return;
        this.mDevice = dev;
    }


    /**
     * Create the list of  WifiP2pServiceResponse instance from supplicant event.
     *
     * @param srcAddr source address of the service response
     * @param tlvsBin byte array containing the binary tlvs data
     * @return if parse failed, return null
     * @hide
     */
    public static List<WifiP2pServiceResponse> newInstance(String srcAddr, byte[] tlvsBin) {
        //updateIndicator not used, and not passed up from supplicant

        List<WifiP2pServiceResponse> respList = new ArrayList<WifiP2pServiceResponse>();
        WifiP2pDevice dev = new WifiP2pDevice();
        dev.deviceAddress = srcAddr;
        if (tlvsBin == null) {
            return null;
        }


        DataInputStream dis = new DataInputStream(new ByteArrayInputStream(tlvsBin));
        try {
            while (dis.available() > 0) {
                /*
                 * Service discovery header is as follows.
                 * ______________________________________________________________
                 * |           Length(2byte)     | Type(1byte) | TransId(1byte)}|
                 * ______________________________________________________________
                 * | status(1byte)  |            vendor specific(variable)      |
                 */
                // The length equals to 3 plus the number of octets in the vendor
                // specific content field. And this is little endian.
                int length = (dis.readUnsignedByte() +
                        (dis.readUnsignedByte() << 8)) - 3;
                int type = dis.readUnsignedByte();
                int transId = dis.readUnsignedByte();
                int status = dis.readUnsignedByte();
                if (length < 0) {
                    return null;
                }
                if (length == 0) {
                    if (status == Status.SUCCESS) {
                        respList.add(new WifiP2pServiceResponse(type, status,
                            transId, dev, null));
                    }
                    continue;
                }
                if (length > MAX_BUF_SIZE) {
                    dis.skip(length);
                    continue;
                }
                byte[] data = new byte[length];
                dis.readFully(data);

                WifiP2pServiceResponse resp;
                if (type ==  WifiP2pServiceInfo.SERVICE_TYPE_BONJOUR) {
                    resp = WifiP2pDnsSdServiceResponse.newInstance(status,
                            transId, dev, data);
                } else if (type == WifiP2pServiceInfo.SERVICE_TYPE_UPNP) {
                    resp = WifiP2pUpnpServiceResponse.newInstance(status,
                            transId, dev, data);
                } else {
                    resp = new WifiP2pServiceResponse(type, status, transId, dev, data);
                }
                if (resp != null && resp.getStatus() == Status.SUCCESS) {
                    respList.add(resp);
                }
            }
            return respList;
        } catch (IOException e) {
            e.printStackTrace();
        }

        if (respList.size() > 0) {
            return respList;
        }
        return null;
    }

    /**
     * Converts hex string to byte array.
     *
     * @param hex hex string. if invalid, return null.
     * @return binary data.
     */
    private static byte[] hexStr2Bin(String hex) {
        int sz = hex.length()/2;
        byte[] b = new byte[hex.length()/2];

        for (int i=0;i<sz;i++) {
            try {
                b[i] = (byte)Integer.parseInt(hex.substring(i*2, i*2+2), 16);
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
        return b;
    }

    @Override
    public String toString() {
        StringBuffer sbuf = new StringBuffer();
        sbuf.append("serviceType:").append(mServiceType);
        sbuf.append(" status:").append(Status.toString(mStatus));
        sbuf.append(" srcAddr:").append(mDevice.deviceAddress);
        sbuf.append(" data:").append(Arrays.toString(mData));
        return sbuf.toString();
    }

    @Override
    public boolean equals(Object o) {
        if (o == this) {
            return true;
        }
        if (!(o instanceof WifiP2pServiceResponse)) {
            return false;
        }

        WifiP2pServiceResponse req = (WifiP2pServiceResponse)o;

        return (req.mServiceType == mServiceType) &&
            (req.mStatus == mStatus) &&
                equals(req.mDevice.deviceAddress, mDevice.deviceAddress) &&
                Arrays.equals(req.mData, mData);
    }

    private boolean equals(Object a, Object b) {
        if (a == null && b == null) {
            return true;
        } else if (a != null) {
            return a.equals(b);
        }
        return false;
    }

    @Override
    public int hashCode() {
        int result = 17;
        result = 31 * result + mServiceType;
        result = 31 * result + mStatus;
        result = 31 * result + mTransId;
        result = 31 * result + (mDevice.deviceAddress == null ?
                0 : mDevice.deviceAddress.hashCode());
        result = 31 * result + (mData == null ? 0 : Arrays.hashCode(mData));
        return result;
    }

    /** Implement the Parcelable interface {@hide} */
    public int describeContents() {
        return 0;
    }

    /** Implement the Parcelable interface {@hide} */
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(mServiceType);
        dest.writeInt(mStatus);
        dest.writeInt(mTransId);
        dest.writeParcelable(mDevice, flags);
        if (mData == null || mData.length == 0) {
            dest.writeInt(0);
        } else {
            dest.writeInt(mData.length);
            dest.writeByteArray(mData);
        }
    }

    /** Implement the Parcelable interface {@hide} */
    public static final @android.annotation.NonNull Creator<WifiP2pServiceResponse> CREATOR =
        new Creator<WifiP2pServiceResponse>() {
            public WifiP2pServiceResponse createFromParcel(Parcel in) {

                int type = in.readInt();
                int status = in.readInt();
                int transId = in.readInt();
                WifiP2pDevice dev = (WifiP2pDevice)in.readParcelable(null);
                int len = in.readInt();
                byte[] data = null;
                if (len > 0) {
                    data = new byte[len];
                    in.readByteArray(data);
                }
                if (type ==  WifiP2pServiceInfo.SERVICE_TYPE_BONJOUR) {
                    return WifiP2pDnsSdServiceResponse.newInstance(status,
                            transId, dev, data);
                } else if (type == WifiP2pServiceInfo.SERVICE_TYPE_UPNP) {
                    return WifiP2pUpnpServiceResponse.newInstance(status,
                            transId, dev, data);
                }
                return new WifiP2pServiceResponse(type, status, transId, dev, data);
            }

            public WifiP2pServiceResponse[] newArray(int size) {
                return new WifiP2pServiceResponse[size];
            }
        };
}
