# -*- coding: utf-8 -*-

""" pySim: Card programmation logic
"""

#
# Copyright (C) 2009-2010  Sylvain Munaut <tnt@246tNt.com>
# Copyright (C) 2011-2023  Harald Welte <laforge@gnumonks.org>
# Copyright (C) 2017 Alexander.Chemeris <Alexander.Chemeris@gmail.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 2 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/>.
#

from typing import Optional, Dict, Tuple
from pySim.ts_102_221 import EF_DIR, EF_ICCID
from pySim.ts_51_011 import DF_GSM
from pySim.transport import LinkBase
import abc

from pySim.utils import *
from pySim.commands import Path

class CardBase:
    """General base class for some kind of telecommunications card."""
    def __init__(self, scc: LinkBase):
        self._scc = scc
        self._aids = []

    def reset(self) -> Optional[Hexstr]:
        rc = self._scc.reset_card()
        if rc == 1:
            return self._scc.get_atr()
        else:
            return None

    def set_apdu_parameter(self, cla: Hexstr, sel_ctrl: Hexstr) -> None:
        """Set apdu parameters (class byte and selection control bytes)"""
        self._scc.cla_byte = cla
        self._scc.sel_ctrl = sel_ctrl

    def get_apdu_parameter(self) -> Tuple[Hexstr, Hexstr]:
        """Get apdu parameters (class byte and selection control bytes)"""
        return (self._scc.cla_byte, self._scc.sel_ctrl)

    def erase(self):
        print("warning: erasing is not supported for specified card type!")
        return

    def file_exists(self, fid: Path) -> bool:
        res_arr = self._scc.try_select_path(fid)
        for res in res_arr:
            if res[1] != '9000':
                return False
        return True

    def read_aids(self) -> List[Hexstr]:
        # a non-UICC doesn't have any applications. Convenience helper to avoid
        # callers having to do hasattr('read_aids') ahead of every call.
        return []

    def read_iccid(self) -> Tuple[Optional[Hexstr], SwHexstr]:
        ef_iccid = EF_ICCID()
        (res, sw) = self._scc.read_binary(ef_iccid.fid)
        if sw == '9000':
            return (dec_iccid(res), sw)
        else:
            return (None, sw)


class SimCardBase(CardBase):
    """Here we only add methods for commands specified in TS 51.011, without
    any higher-layer processing."""
    name = 'SIM'

    def __init__(self, scc: LinkBase):
        super(SimCardBase, self).__init__(scc)
        self._scc.cla_byte = "A0"

    def probe(self) -> bool:
        df_gsm = DF_GSM()
        return self.file_exists(df_gsm.fid)


class UiccCardBase(SimCardBase):
    name = 'UICC'

    def __init__(self, ssc: LinkBase):
        super(UiccCardBase, self).__init__(ssc)
        self._scc.cla_byte = "00"
        # See also: ETSI TS 102 221, Table 9.3
        self._adm_chv_num = 0xA0

    def probe(self) -> bool:
        # EF.DIR is a mandatory EF on all ICCIDs; however it *may* also exist on a TS 51.011 SIM
        ef_dir = EF_DIR()
        return self.file_exists(ef_dir.fid)

    def read_aids(self) -> List[Hexstr]:
        """Fetch all the AIDs present on UICC"""
        self._aids = []
        try:
            ef_dir = EF_DIR()
            # Find out how many records the EF.DIR has
            # and store all the AIDs in the UICC
            rec_cnt = self._scc.record_count(ef_dir.fid)
            for i in range(0, rec_cnt):
                rec = self._scc.read_record(ef_dir.fid, i + 1)
                if (rec[0][0:2], rec[0][4:6]) == ('61', '4f') and len(rec[0]) > 12 \
                        and rec[0][8:8 + int(rec[0][6:8], 16) * 2] not in self._aids:
                    self._aids.append(rec[0][8:8 + int(rec[0][6:8], 16) * 2])
        except Exception as e:
            print("Can't read AIDs from SIM -- %s" % (str(e),))
            self._aids = []
        return self._aids

    @staticmethod
    def _get_aid(adf="usim") -> Optional[Hexstr]:
        aid_map = {}
        # First (known) halves of the U/ISIM AID
        aid_map["usim"] = "a0000000871002"
        aid_map["isim"] = "a0000000871004"
        adf = adf.lower()
        if adf in aid_map:
            return aid_map[adf]
        return None

    def _complete_aid(self, aid: Hexstr) -> Optional[Hexstr]:
        """find the complete version of an ADF.U/ISIM AID"""
        # Find full AID by partial AID:
        if is_hex(aid):
            for aid_known in self._aids:
                if len(aid_known) >= len(aid) and aid == aid_known[0:len(aid)]:
                    return aid_known
        return None

    def adf_present(self, adf: str = "usim") -> bool:
        """Check if the AID of the specified ADF is present in EF.DIR (call read_aids before use)"""
        aid = self._get_aid(adf)
        if aid:
            aid_full = self._complete_aid(aid)
            if aid_full:
                return True
        return False

    def select_adf_by_aid(self, adf: str = "usim") -> Tuple[Optional[Hexstr], Optional[SwHexstr]]:
        """Select ADF.U/ISIM in the Card using its full AID"""
        if is_hex(adf):
            aid = adf
        else:
            aid = self._get_aid(adf)
        if aid:
            aid_full = self._complete_aid(aid)
            if aid_full:
                return self._scc.select_adf(aid_full)
            else:
                # If we cannot get the full AID, try with short AID
                return self._scc.select_adf(aid)
        return (None, None)

def card_detect(scc: LinkBase) -> Optional[CardBase]:
    # UICC always has higher preference, as a UICC might also contain a SIM application
    uicc = UiccCardBase(scc)
    if uicc.probe():
        return uicc

    # this is for detecting a real, classic TS 11.11 SIM card without any UICC support
    sim = SimCardBase(scc)
    if sim.probe():
        return sim

    return None
