/**
 * DesfireManufacturingData.kt
 *
 * Copyright (C) 2011 Eric Butler
 * Copyright (C) 2019  <seil0@mosad.xyz>
 *
 * Authors:
 * Eric Butler <eric@codebutler.com>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.codebutler.farebot.card.desfire

import android.os.Parcel
import android.os.Parcelable
import com.codebutler.farebot.Utils
import org.w3c.dom.Element

import java.io.ByteArrayInputStream

class DesfireManufacturingData : Parcelable {
    private val hwVendorID: Int
    private val hwType: Int
    private val hwSubType: Int
    private val hwMajorVersion: Int
    private val hwMinorVersion: Int
    private val hwStorageSize: Int
    private val hwProtocol: Int

    private val swVendorID: Int
    private val swType: Int
    private val swSubType: Int
    private val swMajorVersion: Int
    private val swMinorVersion: Int
    private val swStorageSize: Int
    private val swProtocol: Int

    private val uid: Int
    private val batchNo: Int
    private val weekProd: Int
    private val yearProd: Int

    constructor(data: ByteArray) {
        val stream = ByteArrayInputStream(data)
        hwVendorID = stream.read()
        hwType = stream.read()
        hwSubType = stream.read()
        hwMajorVersion = stream.read()
        hwMinorVersion = stream.read()
        hwStorageSize = stream.read()
        hwProtocol = stream.read()

        swVendorID = stream.read()
        swType = stream.read()
        swSubType = stream.read()
        swMajorVersion = stream.read()
        swMinorVersion = stream.read()
        swStorageSize = stream.read()
        swProtocol = stream.read()

        // FIXME: This has fewer digits than what's contained in EXTRA_ID, why?
        var buf = ByteArray(7)
        stream.read(buf, 0, buf.size)
        uid = Utils.byteArrayToInt(buf)

        // FIXME: This is returning a negative number. Probably is unsigned.
        buf = ByteArray(5)
        stream.read(buf, 0, buf.size)
        batchNo = Utils.byteArrayToInt(buf)

        // FIXME: These numbers aren't making sense.
        weekProd = stream.read()
        yearProd = stream.read()
    }

    private constructor(element: Element) {
        hwVendorID = Integer.parseInt(element.getElementsByTagName("hw-vendor-id").item(0).textContent)
        hwType = Integer.parseInt(element.getElementsByTagName("hw-type").item(0).textContent)
        hwSubType = Integer.parseInt(element.getElementsByTagName("hw-sub-type").item(0).textContent)
        hwMajorVersion = Integer.parseInt(element.getElementsByTagName("hw-major-version").item(0).textContent)
        hwMinorVersion = Integer.parseInt(element.getElementsByTagName("hw-minor-version").item(0).textContent)
        hwStorageSize = Integer.parseInt(element.getElementsByTagName("hw-storage-size").item(0).textContent)
        hwProtocol = Integer.parseInt(element.getElementsByTagName("hw-protocol").item(0).textContent)

        swVendorID = Integer.parseInt(element.getElementsByTagName("sw-vendor-id").item(0).textContent)
        swType = Integer.parseInt(element.getElementsByTagName("sw-type").item(0).textContent)
        swSubType = Integer.parseInt(element.getElementsByTagName("sw-sub-type").item(0).textContent)
        swMajorVersion = Integer.parseInt(element.getElementsByTagName("sw-major-version").item(0).textContent)
        swMinorVersion = Integer.parseInt(element.getElementsByTagName("sw-minor-version").item(0).textContent)
        swStorageSize = Integer.parseInt(element.getElementsByTagName("sw-storage-size").item(0).textContent)
        swProtocol = Integer.parseInt(element.getElementsByTagName("sw-protocol").item(0).textContent)

        uid = Integer.parseInt(element.getElementsByTagName("uid").item(0).textContent)
        batchNo = Integer.parseInt(element.getElementsByTagName("batch-no").item(0).textContent)
        weekProd = Integer.parseInt(element.getElementsByTagName("week-prod").item(0).textContent)
        yearProd = Integer.parseInt(element.getElementsByTagName("year-prod").item(0).textContent)
    }

    private constructor(parcel: Parcel) {
        hwVendorID = parcel.readInt()
        hwType = parcel.readInt()
        hwSubType = parcel.readInt()
        hwMajorVersion = parcel.readInt()
        hwMinorVersion = parcel.readInt()
        hwStorageSize = parcel.readInt()
        hwProtocol = parcel.readInt()

        swVendorID = parcel.readInt()
        swType = parcel.readInt()
        swSubType = parcel.readInt()
        swMajorVersion = parcel.readInt()
        swMinorVersion = parcel.readInt()
        swStorageSize = parcel.readInt()
        swProtocol = parcel.readInt()

        uid = parcel.readInt()
        batchNo = parcel.readInt()
        weekProd = parcel.readInt()
        yearProd = parcel.readInt()
    }

    override fun writeToParcel(parcel: Parcel, flags: Int) {
        parcel.writeInt(hwVendorID)
        parcel.writeInt(hwType)
        parcel.writeInt(hwSubType)
        parcel.writeInt(hwMajorVersion)
        parcel.writeInt(hwMinorVersion)
        parcel.writeInt(hwStorageSize)
        parcel.writeInt(hwProtocol)

        parcel.writeInt(swVendorID)
        parcel.writeInt(swType)
        parcel.writeInt(swSubType)
        parcel.writeInt(swMajorVersion)
        parcel.writeInt(swMinorVersion)
        parcel.writeInt(swStorageSize)
        parcel.writeInt(swProtocol)

        parcel.writeInt(uid)
        parcel.writeInt(batchNo)
        parcel.writeInt(weekProd)
        parcel.writeInt(yearProd)
    }

    override fun describeContents(): Int {
        return 0
    }

    companion object {

        @Suppress("unused")
        fun fromXml(element: Element): DesfireManufacturingData {
            return DesfireManufacturingData(element)
        }

        @Suppress("unused")
        @JvmField
        val CREATOR: Parcelable.Creator<DesfireManufacturingData> =
            object : Parcelable.Creator<DesfireManufacturingData> {
                override fun createFromParcel(source: Parcel): DesfireManufacturingData {
                    return DesfireManufacturingData(source)
                }

                override fun newArray(size: Int): Array<DesfireManufacturingData?> {
                    return arrayOfNulls(size)
                }
            }
    }
}