# -*- 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 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)
	    # 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
