import Foundation
import CoreNFC


extension CFArray {
    func toSwiftArray<T>() -> [T] {
        let array = Array<AnyObject>(_immutableCocoaArray: self)
        return array.compactMap { $0 as? T }
    }
}

extension Dictionary where Key == String, Value == Any {
    var account: String? {
        guard let account = self[kSecAttrAccount as String] as? String else {
            return nil
        }
        return account
    }
}

@available(iOS 13.0, *)
public class UnifiedNfcApi {
    var stationMap: [Int: Station] = [:]
    var felicaHistoryRetryCount = 0

    func parseData() {
        stationMap = [
            0: Station(id: 0, name: "PARKIR RESKA", subName: "PARKIR RESKA", latitude: "0", longitude: "0"),
            1: Station(id: 1, name: "Tanah Abang", subName: "Tanah Abang", latitude: "-6.18574476", longitude: "106.8108382"),
            67: Station(id: 67, name: "C-Access", subName: "C-Access", latitude: "0", longitude: "0"),
            257: Station(id: 257, name: "Bogor", subName: "Bogor", latitude: "-6.59561005", longitude: "106.7904379"),
            258: Station(id: 258, name: "Cilebut", subName: "Cilebut", latitude: "-6.53050343", longitude: "106.8005885"),
            259: Station(id: 259, name: "Bojonggede", subName: "Bojonggede", latitude: "-6.49326562", longitude: "106.7949173"),
            260: Station(id: 260, name: "Citayam", subName: "Citayam", latitude: "-6.44879141", longitude: "106.8024588"),
            261: Station(id: 261, name: "Depok", subName: "Depok", latitude: "-6.40493394", longitude: "106.8172447"),
            262: Station(id: 262, name: "Depok Baru", subName: "Depok Baru", latitude: "-6.39113047", longitude: "106.821707"),
            263: Station(id: 263, name: "Pondok Cina", subName: "Pondok Cina", latitude: "-6.36905168", longitude: "106.8322114"),
            264: Station(id: 264, name: "Univ. Indonesia", subName: "Univ. Indonesia", latitude: "-6.36075528", longitude: "106.8317544"),
            265: Station(id: 265, name: "Univ. Pancasila", subName: "Univ. Pancasila", latitude: "-6.33894476", longitude: "106.8344241"),
            272: Station(id: 272, name: "Lenteng Agung", subName: "Lenteng Agung", latitude: "-6.33065157", longitude: "106.8349938"),
            273: Station(id: 273, name: "Tanjung Barat", subName: "Tanjung Barat", latitude: "-6.30780817", longitude: "106.8388513"),
            274: Station(id: 274, name: "Pasar Minggu", subName: "Pasar Minggu", latitude: "-6.28440597", longitude: "106.8445384"),
            275: Station(id: 275, name: "Pasar Minggu Baru", subName: "Pasar Minggu Baru", latitude: "-6.26278132", longitude: "106.8518598"),
            276: Station(id: 276, name: "Duren Kalibata", subName: "Duren Kalibata", latitude: "-6.25534623", longitude: "106.8550195"),
            277: Station(id: 277, name: "Cawang", subName: "Cawang", latitude: "-6.24266069", longitude: "106.8588196"),
            278: Station(id: 278, name: "Tebet", subName: "Tebet", latitude: "-6.22606896", longitude: "106.8583004"),
            279: Station(id: 279, name: "Manggarai", subName: "Manggarai", latitude: "-6.20992352", longitude: "106.8502129"),
            280: Station(id: 280, name: "Cikini", subName: "Cikini", latitude: "-6.19856352", longitude: "106.8412599"),
            281: Station(id: 281, name: "Gondangdia", subName: "Gondangdia", latitude: "-6.18594019", longitude: "106.8325942"),
            288: Station(id: 288, name: "Juanda", subName: "Juanda", latitude: "-6.16672229", longitude: "106.8304674"),
            289: Station(id: 289, name: "Sawah Besar", subName: "Sawah Besar", latitude: "-6.16063965", longitude: "106.8276397"),
            290: Station(id: 290, name: "Mangga Besar", subName: "Mangga Besar", latitude: "-6.14979667", longitude: "106.8269796"),
            291: Station(id: 291, name: "Jayakarta", subName: "Jayakarta", latitude: "-6.14134112", longitude: "106.8230834"),
            292: Station(id: 292, name: "Jakarta Kota", subName: "Jakarta Kota", latitude: "-6.13761335", longitude: "106.8146308"),
            293: Station(id: 293, name: "Bekasi", subName: "Bekasi", latitude: "-6.23614485", longitude: "106.9994173"),
            294: Station(id: 294, name: "Kranji", subName: "Kranji", latitude: "-6.22433352", longitude: "106.9793992"),
            295: Station(id: 295, name: "Cakung", subName: "Cakung", latitude: "-6.21929974", longitude: "106.9521357"),
            296: Station(id: 296, name: "Klender Baru", subName: "Klender Baru", latitude: "-6.21743543", longitude: "106.9396893"),
            297: Station(id: 297, name: "Buaran", subName: "Buaran", latitude: "-6.21615092", longitude: "106.9283069"),
            304: Station(id: 304, name: "Klender", subName: "Klender", latitude: "-6.21335877", longitude: "106.8998889"),
            305: Station(id: 305, name: "Jatinegara", subName: "Jatinegara", latitude: "-6.21513342", longitude: "106.8703259"),
            313: Station(id: 313, name: "Tangerang", subName: "Tangerang", latitude: "-6.17679787", longitude: "106.63272688"),
            327: Station(id: 327, name: "Karet", subName: "Karet", latitude: "-6.2008165", longitude: "106.8159002"),
            328: Station(id: 328, name: "Sudirman", subName: "Sudirman", latitude: "-6.202438", longitude: "106.8234505"),
            329: Station(id: 329, name: "Tanah Abang", subName: "Tanah Abang", latitude: "-6.18574476", longitude: "106.8108382"),
            336: Station(id: 336, name: "Palmerah", subName: "Palmerah", latitude: "-6.20740425", longitude: "106.7974463"),
            337: Station(id: 337, name: "Kebayoran", subName: "Kebayoran", latitude: "-6.23718958", longitude: "106.782542"),
            338: Station(id: 338, name: "Pondok Ranji", subName: "Pondok Ranji", latitude: "-6.27633762", longitude: "106.7449376"),
            339: Station(id: 339, name: "Jurang Mangu", subName: "Jurang Mangu", latitude: "-6.28876225", longitude: "106.7291141"),
            340: Station(id: 340, name: "Sudimara", subName: "Sudimara", latitude: "-6.29694285", longitude: "106.7127952"),
            341: Station(id: 341, name: "Rawabuntu", subName: "Rawabuntu", latitude: "-6.31500105", longitude: "106.6761968"),
            342: Station(id: 342, name: "Serpong", subName: "Serpong", latitude: "-6.32004857", longitude: "106.6655717"),
            343: Station(id: 343, name: "Cisauk", subName: "Cisauk", latitude: "-6.3249995", longitude: "106.6407467"),
            344: Station(id: 344, name: "Cicayur", subName: "Cicayur", latitude: "-6.32951436", longitude: "106.6189624"),
            345: Station(id: 345, name: "Parung Panjang", subName: "Parung Panjang", latitude: "-6.34420808", longitude: "106.5698061"),
            352: Station(id: 352, name: "Cilejit", subName: "Cilejit", latitude: "-6.35434367", longitude: "106.5097328"),
            353: Station(id: 353, name: "Daru", subName: "Daru", latitude: "-6.33800742", longitude: "106.4923913"),
            354: Station(id: 354, name: "Tenjo", subName: "Tenjo", latitude: "-6.32725713", longitude: "106.4613542"),
            355: Station(id: 355, name: "Tigaraksa", subName: "Tigaraksa", latitude: "-6.32846118", longitude: "106.4347451"),
            356: Station(id: 356, name: "Maja", subName: "Maja", latitude: "-6.33230387", longitude: "106.3965692"),
            357: Station(id: 357, name: "Citeras", subName: "Citeras", latitude: "-6.33492764", longitude: "106.3327125"),
            358: Station(id: 358, name: "Rangkasbitung", subName: "Rangkasbitung", latitude: "-6.3526711", longitude: "106.251502"),
            374: Station(id: 374, name: "Bekasi Timur", subName: "Bekasitimur", latitude: "-6.246845", longitude: "107.0181248"),
            376: Station(id: 376, name: "Cikarang", subName: "Cikarang", latitude: "-6.2553926", longitude: "107.1451293")
        ]
    }
    var langCode : String?
    var apduRunner = ApduRunner()
    
    public init() {
        langCode = Locale.current.languageCode ?? "en"
        parseData()
    }
    
    func setCallback(apduCallback : ApduCallback){
        apduRunner.setApduCallback(callback: apduCallback)
        apduRunner.setUnifiedNfcApi(nfcApi: self)
    }
    
    func setApduRunner(apRunner : ApduRunner){
        self.apduRunner = apRunner
    }
    
    public func checkIfNfcSupported() -> Bool {
        return NFCTagReaderSession.readingAvailable
    }
    
    public func searchCard(){
        apduRunner.startScan()
    }
    
    public func checkCard(){
        apduRunner.exchangeApdu(apduCommand: EmoneyApduCommands.BRIZZI_INIT_APDU, completionHandler: {response in
            if (response.sw1 == 0x91 && response.sw2 == 0x00){
                debugLog("brizzi card")
                let brizzi = BrizziApi()
                brizzi.setApduRunner(apRunner: self.apduRunner)
                brizzi.getUid()
            } else {
                self.checkNext01()
            }
        })
    }
    
    public func checkFelicaCard(tag: NFCFeliCaTag){
        readFelicaCard(tag: tag)
    }

    private func logFelica(_ message: String) {
        _ = message
        // print("[FeliCa] \(message)")
        // debugLog("[FeliCa] \(message)")
    }
    
    func readFelicaCard(tag: NFCFeliCaTag){
        let kmt = Emoney()
        logFelica("Start read | currentIDm=\(tag.currentIDm.map { String(format: "%02X", $0) }.joined()) | currentSystemCode=\(tag.currentSystemCode.map { String(format: "%02X", $0) }.joined())")
        
        let serviceCode = Data([0x0B, 0x30])
        let blockList = Data([0x80, 0x00])
        
        tag.readWithoutEncryption(
                serviceCodeList: [serviceCode],
                blockList: [blockList]
            ) { (status1, status2, blockData, error) in
                
                if let error = error {
                    self.logFelica("Card info read failed | error=\(error.localizedDescription)")
                    self.apduRunner.nfcApi?.stopCheckCard(message: "Gagal membaca: \(error.localizedDescription)")
                    return
                }
                
                // Cek status keberhasilan dari kartu (0x00 0x00 berarti sukses)
                guard status1 == 0x00 && status2 == 0x00 else {
                    self.logFelica("Card info read failed | status1=\(status1) | status2=\(status2)")
                    self.apduRunner.nfcApi?.stopCheckCard(message: "Error Status: \(status1) \(status2)")
                    return
                }
                for (index, data) in blockData.enumerated() {
                    let hex = data.map { String(format: "%02X", $0) }.joined()
                    self.logFelica("Card info block \(index) raw=\(hex)")
                    if let cardNumberString = String(data: data, encoding: .utf8) {
                        self.logFelica("Card number parsed=\(cardNumberString)")
                        kmt.setCardLabel("KMT")
                        kmt.setCardNumber(cardNumberString)
                        self.readFelicaBalance(tag: tag, kmt: kmt)
                    } else {
                        self.logFelica("Card number parse failed for block \(index)")
                    }
                }
            }
    }
    
    func readFelicaBalance(tag: NFCFeliCaTag, kmt: Emoney){
        let serviceCode = Data([0x17, 0x10])
        let blockList = Data([0x80, 0x00])

        tag.readWithoutEncryption(
            serviceCodeList: [serviceCode],
            blockList: [blockList]
        ) { (status1, status2, blockData, error) in
            if let error = error {
                self.logFelica("Balance read failed | error=\(error.localizedDescription)")
                self.apduRunner.nfcApi?.stopCheckCard(message: "Gagal membaca: \(error.localizedDescription)")
                return
            }
            
            if status1 == 0x00 && status2 == 0x00 {
                guard let firstBlock = blockData.first, firstBlock.count >= 4 else {
                    self.logFelica("Balance block missing or too short")
                    return
                }
                self.logFelica("Balance raw=\(firstBlock.map { String(format: "%02X", $0) }.joined())")
                let cardBalance = [UInt8](firstBlock)
                var y: Int = 0
                for x in 0..<4 {
                    y += Int(cardBalance[x]) << (x * 8)
                }

                let formatter = NumberFormatter()
                formatter.locale = Locale(identifier: "id_ID")
                formatter.numberStyle = .decimal
                kmt.setBalance(y)
                if let balance = formatter.string(from: NSNumber(value: y)) {
                    self.logFelica("Balance parsed=\(y) | formatted=\(balance)")
                }
                self.felicaHistoryRetryCount = 0
                self.readFelicaCardHistory(tag: tag, kmt: kmt)
            } else {
                self.logFelica("Balance read failed | status1=\(status1) | status2=\(status2)")
//                kmt.setTampilRiwayat(false)
//                self.apduRunner.callback?.complete(emoney: kmt)
//                self.apduRunner.sessionEx?.alertMessage = "readFinish".localizeString(string: self.langCode!)
//                self.apduRunner.invalidateSession()
            }
        }
    }
    
    func readFelicaCardHistory(tag: NFCFeliCaTag, kmt: Emoney){
        let serviceCode = Data([0x0F, 0x20])

        // 2. Buat daftar 15 blok (Blok 0 sampai 14) secara otomatis
        var blockList = [Data]()
        for i in 0..<15 {
            blockList.append(Data([0x80, UInt8(i)]))
        }

        // 3. Panggil fungsi pembacaan
        tag.readWithoutEncryption(
            serviceCodeList: [serviceCode],
            blockList: blockList
        ) { (status1, status2, blockData, error) in
            var riwayatList: [RiwayatCard] = []
            if let error = error {
                self.logFelica("History read failed | error=\(error.localizedDescription)")
                self.retryFelicaHistoryRead(tag: tag, kmt: kmt, reason: "error \(error.localizedDescription)")
                return
            }
            
            if status1 == 0x00 && status2 == 0x00 {
                self.logFelica("History read success | blocks=\(blockData.count)")
                // blockData akan berisi array of Data, masing-masing 16 byte
                for (index, data) in blockData.enumerated() {
                    let riwayat = RiwayatCard()
                    var normal = true
                    let rawHex = data.map { String(format: "%02X", $0) }.joined()
                    self.logFelica("History block \(index) raw=\(rawHex)")
                    guard data.count >= 12 else {
                        self.logFelica("History block \(index) skipped | reason=too_short | count=\(data.count)")
                        continue
                    }
                    let subId = data.subdata(in: 8..<10)
                    
                    let uid = self.convert(bytes: [UInt8](subId))
                    self.logFelica("History block \(index) stationId=\(uid)")
                    if (uid == 0){
                        normal = false
                    }
                    if data.count >= 13 {
                        let transactionKind = self.felicaTransactionKind(for: [UInt8](data), stationId: uid)
                        riwayat.setProsesTipe(transactionKind.prosesTipe)
                        riwayat.setTitle(transactionKind.title.localizeString(string: self.langCode!))
                        self.logFelica("History block \(index) signature=\(transactionKind.signature) | kind=\(transactionKind.logLabel)")
                    }
                    if let station = self.stationMap[uid]{
                        self.logFelica("History block \(index) stationName=\(station.name)")
                        riwayat.setLocationName(station.name.uppercased(with: .autoupdatingCurrent))
                    }
//                    let station = self.stationMap[uid]
//                    print("station", station!)
//                    riwayat.setPlace(self.stationMap[uid]!.name)
                    if (normal){
                        
                        let subData = data.subdata(in: 0..<4)

                        if let date = self.getDate(data: [UInt8](subData)) {
                            riwayat.setTransactionTime(date)
                        }
                        let formatter = DateFormatter()
                        formatter.locale = Locale(identifier: "id_ID") // Format Indonesia
                        formatter.dateFormat = "dd MMMM yyyy, HH:mm"

                        if let date = riwayat.getTransationTime() {
                            let dateString = formatter.string(from: date)
                            self.logFelica("History block \(index) timestamp=\(dateString)")
                        }
                        
                        let amn = data.subdata(in: 4..<8)
                        let amount = amn.withUnsafeBytes { $0.load(as: Int32.self).bigEndian }
                            
                        //print("Amount: \(amount)")
                        
//                        if (data.count > 10){
//                            let type = data[10]
//                            print(type)
//                            switch type {
//                            case 0x01:
//                                print("Pembayaran")
//                            case 0x00:
//                                print("Topup")
//                            default:
//                                print("Other")
//                            }
//
//                            let subId = data.subdata(in: 8..<10)
//
//                            let uid = self.convert(bytes: [UInt8](subId))
//                            print("station: \(uid)")
//                        }
                        riwayat.setAmount(Int(amount))
                        let nformatter = NumberFormatter()
                        nformatter.locale = Locale(identifier: "id_ID")
                        nformatter.numberStyle = .decimal
                        if let balance = nformatter.string(from: NSNumber(value: amount)) {
                            self.logFelica("History block \(index) amount=\(amount) | formatted=\(balance)")
                        }
                    } else {
                        self.logFelica("History block \(index) mode=RESKA_PARKIR")
                        
                        let stringData = data.map { String(format: "%02X", $0) }.joined()
                        
                        let inputFormatter = DateFormatter()
                        inputFormatter.dateFormat = "ddMMyyyyHHmmssSS"

                        let finalData = stringData.prefix(16)
                        // 2. Konversi String ke objek Date
                        if let date = inputFormatter.date(from: String(finalData)) {
                            
                            // 3. Inisialisasi Formatter untuk mengubah ke format tujuan
                            let outputFormatter = DateFormatter()
                            outputFormatter.dateFormat = "dd MMM yyyy HH:mm"
                            
                            let result = outputFormatter.string(from: date)
                            riwayat.setTransactionTime(date)
                            self.logFelica("History block \(index) timestamp=\(result)")
                        } else {
                            self.logFelica("History block \(index) timestamp_parse_failed")
                        }
                        let amn = data.subdata(in: 8..<12)
                        let amount = amn.withUnsafeBytes { $0.load(as: Int32.self).bigEndian }
                        riwayat.setAmount(Int(amount))
                        //print("Amount: \(amount)")
                        
                        
                        let nformatter = NumberFormatter()
                        nformatter.locale = Locale(identifier: "id_ID")
                        nformatter.numberStyle = .decimal
                        if let balance = nformatter.string(from: NSNumber(value: amount)) {
                            self.logFelica("History block \(index) amount=\(amount) | formatted=\(balance)")
                        }
                    }
                    let title = riwayat.getTitle() ?? "-"
                    let location = riwayat.getLocationName() ?? "-"
                    self.logFelica("History block \(index) summary | title=\(title) | prosesTipe=\(riwayat.getProsesTipe()) | location=\(location)")
                    riwayatList.append(riwayat)
                }
                kmt.setRiwayatList(riwayatList)
                kmt.setTampilRiwayat(true)
                self.logFelica("History parsed total=\(riwayatList.count)")
                self.apduRunner.callback?.complete(emoney: kmt)
                self.apduRunner.sessionEx?.alertMessage = "readFinish".localizeString(string: self.langCode!)
                self.apduRunner.invalidateSession()
            } else {
                self.logFelica("History read failed | status1=\(status1) | status2=\(status2)")
                self.retryFelicaHistoryRead(tag: tag, kmt: kmt, reason: "status \(status1)-\(status2)")
            }
        }
    }

    private func retryFelicaHistoryRead(tag: NFCFeliCaTag, kmt: Emoney, reason: String) {
        if felicaHistoryRetryCount < 1 {
            felicaHistoryRetryCount += 1
            logFelica("Retrying history read | reason=\(reason)")
            readFelicaCardHistory(tag: tag, kmt: kmt)
        } else {
            apduRunner.callback?.complete(emoney: kmt)
            apduRunner.sessionEx?.alertMessage = "readFinish".localizeString(string: self.langCode!)
            apduRunner.invalidateSession()
        }
    }
    
    func getDate(data: [UInt8]) -> Date? {
        // 1. Tentukan TimeZone Jakarta
        let timeZone = TimeZone(identifier: "Asia/Jakarta") ?? .current
        var calendar = Calendar(identifier: .gregorian)
        calendar.timeZone = timeZone
        
        // 2. Set tanggal dasar (1 Januari 2000, 07:00:00)
        var components = DateComponents()
        components.year = 2000
        components.month = 1
        components.day = 1
        components.hour = 7
        components.minute = 0
        components.second = 0
        
        guard let baseDate = calendar.date(from: components) else { return nil }
        
        // 3. Ambil selisih detik dari data byte
        let secondsToAdd = convert(bytes: data)
        
        // 4. Tambahkan detik ke baseDate
        let finalDate = calendar.date(byAdding: .second, value: secondsToAdd, to: baseDate)
        
        return finalDate
    }
    
    func convert(bytes: [UInt8]) -> Int {
        switch bytes.count {
        case 0:
            return 0
        case 1:
            return Int(bytes[0])
        case 2:
            // Big-endian: (byte[0] << 8) | byte[1]
            return (Int(bytes[0]) << 8) | Int(bytes[1])
        case 3:
            // (byte[0] << 16) | (byte[1] << 8) | byte[2]
            return (Int(bytes[0]) << 16) | (Int(bytes[1]) << 8) | Int(bytes[2])
        default:
            // Padanan ByteBuffer.wrap(bArr).getInt() (Big-endian)
            return Int(bytes.withUnsafeBytes { $0.load(as: Int32.self).bigEndian })
        }
    }

    private func felicaTransactionKind(for bytes: [UInt8], stationId: Int) -> (prosesTipe: Int, title: String, logLabel: String, signature: String) {
        let signatureBytes = Array(bytes[10...12])
        let signature = signatureBytes.map { String(format: "%02X", $0) }.joined(separator: " ")
        
        if stationId == 0 {
            return (1, "payment", "Parkir", signature)
        }

        switch signatureBytes {
        case [0x00, 0x02, 0x00],
             [0x02, 0x01, 0x00],
             [0x03, 0x01, 0x00]:
            return (0, "topup", "Topup", signature)
        case [0x01, 0x01, 0x01],
             [0x01, 0x58, 0x01],
             [0x03, 0x61, 0x01]:
            return (1, "payment", "Pembayaran", signature)
        default:
            let terminalMarker = bytes[12]
            switch terminalMarker {
            case 0x00:
                return (0, "topup", "Topup (fallback sig[2])", signature)
            case 0x01:
                return (1, "payment", "Pembayaran (fallback sig[2])", signature)
            default:
                return (1, "payment", "Other", signature)
            }
        }
    }
    
    public func stopCheckCard(message : String){
        apduRunner.sessionEx?.invalidate(errorMessage: message)
    }
    
    private func checkNext01(){
        apduRunner.exchangeApdu(apduCommand: EmoneyApduCommands.FLAZZ_INIT_APDU, completionHandler: {response in
            if (response.sw1 == 0x90 && response.sw2 == 0x00){
                debugLog("flazz card")
                let flazz = BcaFlazzApi()
                flazz.setApduRunner(apRunner: self.apduRunner)
                flazz.checkFlazzCard()
            } else {
                self.checkNext02()
            }
        })
    }
    
    private func checkNext02(){
        apduRunner.exchangeApdu(apduCommand: EmoneyApduCommands.TAPCASH_INIT_APDU, completionHandler: {response in
            if (response.sw1 == 0x90 && response.sw2 == 0x00){
                debugLog("tapcash card")
                let tapCash = TapCashApi()
                tapCash.setApduRunner(apRunner: self.apduRunner)
                tapCash.checkBalance()
            } else {
                self.checkNext03()
            }
        })
    }
    
    private func checkNext03(){
        apduRunner.exchangeApdu(apduCommand: EmoneyApduCommands.EMONEY_INIT_APDU, completionHandler: {response in
            if (response.sw1 == 0x90 && response.sw2 == 0x00){
                debugLog("emoney card")
                let emoney = MandiriEmoneyApi()
                emoney.setApduRunner(apRunner: self.apduRunner)
                emoney.getCardNumber()
            } else {
                self.checkNext04()
            }
        })
    }
    
    private func checkNext04(){
        apduRunner.exchangeApdu(apduCommand: EmoneyApduCommands.JACKCARD_INIT_APDU, completionHandler: {response in
            if (response.sw1 == 0x90 && response.sw2 == 0x00){
                debugLog("jack card")
                let jack = JackCardApi()
                jack.setApduRunner(apRunner: self.apduRunner)
                jack.getBalance(resp: response.getData())
            } else {
                self.checkNext05()
            }
        })
    }
    
    private func checkNext05(){
        apduRunner.exchangeApdu(apduCommand: EmoneyApduCommands.MEGA_APDU01, completionHandler: {response in
            if (response.sw1 == 0x90 && response.sw2 == 0x00){
                debugLog("megacash")
                let mega = MegaCashApi()
                mega.setApduRunner(apRunner: self.apduRunner)
                mega.getBalance(resp: response.getData())
            } else {
                self.apduRunner.invalidateSession(msg: "Card not supported")
            }
        })
    }
}
