# -*- 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
from pySim.ts_51_011 import DF_GSM
import abc

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

class CardBase:
    """General base class for some kind of telecommunications card."""
    def __init__(self, scc: SimCardCommands):
        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 []


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: SimCardCommands):
        super(SimCardBase, self).__init__(scc)
        self._scc.cla_byte = "A0"
        self._scc.sel_ctrl = "0000"

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


class UiccCardBase(SimCardBase):
    name = 'UICC'

    def __init__(self, scc: SimCardCommands):
        super(UiccCardBase, self).__init__(scc)
        self._scc.cla_byte = "00"
        self._scc.sel_ctrl = "0004"  # request an FCP
        # See also: ETSI TS 102 221, Table 9.3
        self._adm_chv_num = 0x0A

    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", scc: Optional[SimCardCommands] = None) -> Tuple[Optional[Hexstr], Optional[SwHexstr]]:
        """Select ADF.U/ISIM in the Card using its full AID"""
        # caller may pass a custom scc; we fall back to default
        scc = scc or self._scc
        if is_hex(adf):
            aid = adf
        else:
            aid = self._get_aid(adf)
        if aid:
            aid_full = self._complete_aid(aid)
            if aid_full:
                return scc.select_adf(aid_full)
            else:
                # If we cannot get the full AID, try with short AID
                return scc.select_adf(aid)
        return (None, None)

def card_detect(scc: SimCardCommands) -> 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
