/*
 *  Copyright © 2016, 2017, 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.
 */

import Foundation
import DeviceLib

/**
 * Representation of an iBeacon.
 */
public class IBeacon : Beacon {
    
    var majorVersion: String!
    var majorVersionNum: NSNumber!
    var minorVersion: String!
    var minorVersionNum: NSNumber!
    var manufacturerData: String!
    
    init(identifier: String, UUID: String, manufacturerData: String,
         serialNumber: String,
         address: String, modelNumber: String, mssi: Int, majorVersion: String,
         minorVersion: String, rawData: [UInt8], isSimulated: Bool,
         isRestricted: Bool) {
        
        super.init(identifier: identifier, UUID: UUID,
                   serialNumber: serialNumber, address: address,
                   modelNumber: modelNumber, mssi: mssi, rawData: rawData,
                   type: Type.IBEACON, isSimulated: isSimulated,
                   isRestricted: isRestricted)
        self.majorVersion = majorVersion
        self.minorVersion = minorVersion
        self.manufacturerData = manufacturerData
        self.hardwareId = identifier
    }
    
    public func getMajorVersion() -> String {
        return self.majorVersion
    }
    
    public func getMajorVersionNum() -> NSNumber {
        return self.majorVersionNum
    }
    
    public func getMinorVersion() -> String {
        return self.minorVersion
    }
    
    public func getMinorVersionNum() -> NSNumber {
        return self.minorVersionNum
    }
    
    public func getManufacturerData() -> String {
        return self.manufacturerData
    }
    
    public static func getSimulatedInstance(minorNum: UInt8,
                                            beaconUUID: String) -> IBeacon {
        var minor = [UInt8](repeating: 0, count: 2)
        minor[1] = minorNum
        let mssi: Int = -67
        let UUID = beaconUUID
        let majorVersion = MAJOR_NUM
        let minorVersion = getString(data: minor)
        let manufacturerDataString = "Sample";
        let identifier = UUID + ":" + majorVersion + ":" +  minorVersion

        let serialNumber = majorVersion + ":" + minorVersion
        let rawData = [UInt8](repeating: 0, count: 1)
        let modelNumber = "MN-" + identifier
        let address = "Simulated Bluetooth Device"
        
        return IBeacon(identifier: identifier, UUID: UUID,
                       manufacturerData: manufacturerDataString,
                       serialNumber: serialNumber, address: address,
                       modelNumber: modelNumber, mssi: mssi,
                       majorVersion: majorVersion,
                       minorVersion: minorVersion, rawData: rawData,
                       isSimulated: true,
                       isRestricted: false)
    }
    
    public static func getInstance(majorNum: NSNumber, minorNum: NSNumber,
                                   beaconUUID: UUID) -> IBeacon {
        let mssi: Int = -67
        var majorVersion = String(format: "%x", Int(truncating: majorNum))
        while (majorVersion.count < 4) {
            majorVersion = "0" + majorVersion
        }
        var minorVersion = String(format: "%x", Int(truncating: minorNum))
        while (minorVersion.count < 4) {
            minorVersion = "0" + majorVersion
        }
        let manufacturerDataString = "EST";
        let identifier =  beaconUUID.uuidString + ":" + majorVersion + ":" +
            minorVersion
        let serialNumber = majorVersion + ":" + minorVersion
        let rawData = [UInt8](repeating: 0, count: 1)
        let modelNumber = "iBeacon"
        let address = "Bluetooth Device"
        
        let newBeacon = IBeacon(identifier: identifier,
                                UUID: beaconUUID.uuidString,
                                manufacturerData: manufacturerDataString,
                                serialNumber: serialNumber, address: address,
                                modelNumber: modelNumber, mssi: mssi,
                                majorVersion: majorVersion,
                                minorVersion: minorVersion,
                                rawData: rawData, isSimulated: false,
                                isRestricted: false)
        newBeacon.majorVersionNum = majorNum
        newBeacon.minorVersionNum = minorNum
        
        return newBeacon
    }
}
