/*
 * Copyright (c) 2016 Oracle and/or its affiliates.  All rights reserved.
 *
 * This software is dual-licensed to you under the MIT License (MIT) and 
 * the Universal Permissive License (UPL).  See the LICENSE file in the root
 * directory for license terms.  You may choose either license, or both.
 */

package com.oracle.iot.sample;

/**
 * Representation of an iBeacon.
 */
public class IBeacon extends Beacon{
    private static final int UUID_POSITION = 9;
    private static final int MAJOR_VERSION_POSITION = 25;
    private static final int MINOR_VERSION_POSITION = 27;
    private static final int MSSI_BYTE_POSITION = 29;
    private static final int MANUFACTURER_DATA_POSITION = 5;

    String majorVersion;
    String minorVersion;
    String manufacturerData;

    private IBeacon(String identifier, String UUID, String manufacturerData, String serialNumber,
                    String address, String modelNumber, int mssi, String majorVersion,
                    String minorVersion, byte[] rawData, boolean isSimulated) {
        super(identifier, UUID, serialNumber, address, modelNumber, mssi, rawData, Type.IBEACON, isSimulated);
        this.majorVersion = majorVersion;
        this.minorVersion = minorVersion;
        this.manufacturerData = manufacturerData;
    }

    public String getMajorVersion() {
        return majorVersion;
    }

    public String getMinorVersion() {
        return minorVersion;
    }

    public String getManufacturerData() {
        return manufacturerData;
    }

    public static IBeacon getInstance(byte packet[], String address, String name){
        byte[] uuid = new byte[16];
        byte[] major = new byte[2];
        byte[] minor = new byte[2];
        byte[] manufacturerData = new byte[4];
        int mssi = packet[MSSI_BYTE_POSITION];
        System.arraycopy(packet, UUID_POSITION, uuid, 0, 16);
        System.arraycopy(packet, MAJOR_VERSION_POSITION, major, 0, 2);
        System.arraycopy(packet, MINOR_VERSION_POSITION, minor, 0, 2);
        System.arraycopy(packet, MANUFACTURER_DATA_POSITION, manufacturerData, 0, 4);
        String UUID = getString(uuid);
        String majorVersion = getString(major);
        String minorVersion = getString(minor);
        String manufacturerDataString = getString(manufacturerData);
        String identifier = UUID + ":" + majorVersion + ":" +  minorVersion;
        String serialNumber = majorVersion + ":" + minorVersion;
        byte[] rawData = packet.clone();
        String modelNumber = name!=null?name:"none";
        return new IBeacon(identifier, UUID, manufacturerDataString, serialNumber, address,
                modelNumber, mssi, majorVersion, minorVersion, rawData, false);
    }

    public static IBeacon getSimulatedInstance(byte minorNum, String beaconUUID){
        byte[] minor = new byte[2];
        minor[1] = minorNum;
        int mssi = -67;
        String UUID = beaconUUID;
        String majorVersion = MAJOR_NUM;
        String minorVersion = getString(minor);
        String manufacturerDataString = "Sample";
        String identifier = UUID + ":" + majorVersion + ":" +  minorVersion;
        String serialNumber = majorVersion + ":" + minorVersion;
        byte[] rawData = new byte[1];
        String modelNumber = "Sample iBeacon";
        String address = "Simulated Bluetooth Device";
        return new IBeacon(identifier, UUID, manufacturerDataString, serialNumber, address,
                modelNumber, mssi, majorVersion, minorVersion, rawData, true);
    }

    @Override
    public String toString(){
        StringBuffer sb = new StringBuffer();
        sb.append("Identifier: " + identifier + "\n");
        sb.append("UUID: " + UUID + "\n");
        sb.append("Major Version: " + majorVersion + "\n");
        sb.append("Minor Version: " + minorVersion + "\n");
        sb.append("Model Number: " + modelNumber + "\n");
        sb.append("Serial Number: " + serialNumber + "\n");
        sb.append("Address: " + address + "\n");
        sb.append("MSSI: " + mssi + "\n");
        if (!isSimulated) {
            sb.append("RSSI: " + getRssi() + " (" + rssiRaw + ")\n");
            sb.append("Distance: " + getDistance() + " m (" + calculateDistance(rssiRaw) + " m)\n");
        } else {
            sb.append("RSSI: " + getRssi() + "\n");
            sb.append("Distance: " + getDistance() + "\n");
        }
        return sb.toString();
    }
}

