package com.wayne.www.waynelib.fdc.model


import com.wayne.www.waynelib.listener.NotifyPropertyChanged
import com.wayne.www.waynelib.common.Tuple

import java.util.ArrayList
import java.util.Collections

/**
 * Created by Think on 3/15/2016.
 */
public class Nozzle : NotifyPropertyChanged() {
    var Product: Product? = null
    var Pump: Pump? = null
    public var NozzleNo: Int = 0
    var GradeName: String = ""
    var FuelPrice: String = ""
    var CurrentAmount: String  = ""
    var CurrentVolumn: String  = ""
    var NozzleName: String? = null
    var SiteNozzleNo: Int = 1
    private var transactions: MutableList<FuelSaleTransaction>? = mutableListOf()
    private var finishedTransactions: MutableList<FuelSaleTransaction>? = mutableListOf()
    var selectedTransaction: FuelSaleTransaction? = null
    var currentState = PumpOrNozzleState.Idle
    private var moneyTotalizerValue: Double = 0.toDouble()
    private var volumnTotalizerValue: Double = 0.toDouble()

    /* get the first stacked trx on this nozzle*/
    val transaction: FuelSaleTransaction?
        get() = if (this.transactions != null && this.transactions!!.size > 0) this.transactions!![0] else null

    /* get the all stacked trxs on this nozzle*/
    val latestTransactions: List<FuelSaleTransaction>?
        get() {
            if (this.transactions == null) return null
            val trxs = ArrayList<FuelSaleTransaction>()
            for (i in transactions!!.indices) {
                trxs.add(this.transactions!![i])
            }
            if (trxs.size == 0) return null
            Collections.sort(trxs, FuelSaleTransactionComparer())
            return trxs
        }

    /* get the all stacked trxs on this nozzle*/
    val availableTransactions: List<FuelSaleTransaction>?
        get() {
            if (this.transactions == null) return null
            val trxs = ArrayList<FuelSaleTransaction>()
            for (i in transactions!!.indices) {
                trxs.add(this.transactions!![i])
            }
            if (trxs.size == 0) return null
            Collections.sort(trxs, FuelSaleTransactionComparer())
            return trxs
        }

//    val availableTransactionStatus: List<TransactionStatus>?
//        get() {
//            if (this.transactions == null || this.transactions!!.size == 0) return null
//            var trxs = ArrayList<TransactionStatus>()
//
//            for (fuelTrx in this.transactions!!) {
//                trxs.add(TransactionStatus(id = fuelTrx.))
//            }
//
//            return trxs
//        }

    val totalizerValues: Tuple<Double, Double>
        get() = Tuple(this.moneyTotalizerValue, this.volumnTotalizerValue)

    val latestUnpaidTrx: FuelSaleTransaction?
        get() {
            if (this.transactions == null) return null
            val trxs = ArrayList<FuelSaleTransaction>()
            for (i in transactions!!.indices) {
                trxs.add(this.transactions!![i])
            }
            if (trxs.size == 0) return null
            Collections.sort(trxs, FuelSaleTransactionComparer())
            return trxs[0]
        }

    fun setState(newState: PumpOrNozzleState) {
        this.currentState = newState
        super.notifyAllListeners(this, "State")
    }

    fun setGradeInfo(gradeName: String, fuelPrice: String) {
        if (!gradeName.isEmpty()) {
            this.GradeName = gradeName
            this.FuelPrice = fuelPrice
            super.notifyAllListeners(this, "GradeInfo")
        }
    }

    fun setGradeInfo(gradeName: String) {
        if (!gradeName.isEmpty()) {
            this.GradeName = gradeName
            super.notifyAllListeners(this, "GradeInfo")
        }
    }

    fun setTotalizer(currentAmount: String, currentVolumn: String, currentFuelPrice: String) {
        this.CurrentAmount = currentAmount
        this.CurrentVolumn = currentVolumn
        this.FuelPrice = currentFuelPrice
        super.notifyAllListeners(this, "FuelingInProgress")
    }

    /* get the all stacked trxs on this nozzle*/
    fun getTransactions(): List<FuelSaleTransaction>? {
        return this.transactions
    }

    /* get the all stacked trxs on this nozzle*/
    fun getFinishedTransactions(): List<FuelSaleTransaction>? {
        return this.finishedTransactions
    }

    /* stack a pending for processing trx to this nozzle
    *  will have a check for 'newTrx' if already in stacked list, if duplicated, return false.
    *  otherwise, return true.
    * */
    fun stackOrUpdateTransaction(newTrx: FuelSaleTransaction, refreshUI: Boolean = true) {
        if (this.transactions == null) this.transactions = ArrayList()
        for (i in this.transactions!!.indices) {
            if (this.transactions!![i] == newTrx) {
                this.transactions!![i].State = newTrx.State
                this.transactions!![i].TransactionTimeStamp = newTrx.TransactionTimeStamp
                this.transactions!![i].AuthorisationApplicationSender = newTrx.AuthorisationApplicationSender
                this.transactions!![i].LockingApplicationSender = newTrx.LockingApplicationSender
                this.transactions!![i].ReservingDeviceId = newTrx.ReservingDeviceId
                if (refreshUI) {
                    super.notifyAllListeners(this, "TransactionUpdated")
                }
                return
            }
        }

        this.transactions!!.add(newTrx)
        if (this.transactions!!.size > LATEST_TRX_COUNT) {
            this.transactions!!.removeAt(0)
        }
        if (refreshUI) {
            super.notifyAllListeners(this, "Transaction")
        }
    }

    fun setTotalizerValues(moneyTotalizerValue: Double, volumnTotalizerValue: Double) {
        this.moneyTotalizerValue = moneyTotalizerValue
        this.volumnTotalizerValue = volumnTotalizerValue
        super.notifyAllListeners(this, "Totalizer")
    }

    /* remove a trx from the stacked trx list.
    *  if found and removed, return True.
    *  otherwise, false.
    * */
    fun finishTransaction(trxToFinish: FuelSaleTransaction): Boolean {
        if (this.transactions == null) return false
        for (i in this.transactions!!.indices) {
            if (this.transactions!![i] == trxToFinish) {
                finishedTransactions!!.add(trxToFinish)
                if (finishedTransactions!!.size > FINISHED_TRX_MAX) {
                    finishedTransactions!!.removeAt(0)
                }
                this.transactions!!.removeAt(i)
                super.notifyAllListeners(this, "Transaction")
                return true
            }
        }

        return false
    }

    fun clearAllTransaction(updateUi: Boolean = true) {
        if (this.transactions != null) {
            this.transactions = null
            if (updateUi) {
                super.notifyAllListeners(this, "Transaction")
            }
        }
    }

    override fun equals(obj: Any?): Boolean {
        if (obj == null)
            return false
        if (obj === this)
            return true
        if (obj !is Nozzle)
            return false

        val target = obj as Nozzle?
        if (target!!.Product == null && this.Product != null || target.Product != null && this.Product == null)
            return false
        return if (target.Product == null) target.NozzleNo == this.NozzleNo else target.NozzleNo == this.NozzleNo && target.Product == this.Product


    }

    override fun hashCode(): Int {
        return this.Product!!.hashCode() xor this.NozzleNo
    }

    companion object {
        var LATEST_TRX_COUNT = 8
        var FINISHED_TRX_MAX = 4

        fun convert(fdcNozzle: com.wayne.www.waynelib.fdc.message.Nozzle, product: Product, pump: Pump): Nozzle {
            val modelNozzle = Nozzle()
            modelNozzle.NozzleNo = fdcNozzle.nozzleNo!!
            modelNozzle.Product = product
            modelNozzle.Pump = pump
            return modelNozzle
        }
    }
}
