#!/usr/bin/env python3

# Interactive shell for working with SIM / UICC / USIM / ISIM cards
#
# (C) 2022 by Harald Welte <laforge@osmocom.org>
#
# 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 List

import cmd2
from cmd2 import CommandSet, with_default_category, with_argparser
import argparse

from pySim.ts_31_102 import EF_UST_map, EF_USIM_ADF_map
from pySim.ts_31_103 import EF_IST_map, EF_ISIM_ADF_map

from pySim.exceptions import *
from pySim.utils import h2b, swap_nibbles, b2h, JsonEncoder

from pySim.ts_102_221 import *

@with_default_category('TS 102 222 Administrative Commands')
class Ts102222Commands(CommandSet):
    """Administrative commands for telecommunication applications."""

    def __init__(self):
        super().__init__()

    delfile_parser = argparse.ArgumentParser()
    delfile_parser.add_argument('--force-delete', action='store_true',
            help='I really want to permanently delete the file. I know pySim cannot re-create it yet!')
    delfile_parser.add_argument('NAME', type=str, help='File name or FID to delete')

    @cmd2.with_argparser(delfile_parser)
    def do_delete_file(self, opts):
        """Delete the specified file. DANGEROUS!  See TS 102 222 Section 6.4.
        This will permanently delete the specified file from the card.
        pySim has no support to re-create files yet, and even if it did, your card may not allow it!"""
        if not opts.force_delete:
            self._cmd.perror("Refusing to permanently delete the file, please read the help text.")
            return
        f = self._cmd.lchan.get_file_for_selectable(opts.NAME)
        (data, sw) = self._cmd.card._scc.delete_file(f.fid)

    def complete_delete_file(self, text, line, begidx, endidx) -> List[str]:
        """Command Line tab completion for DELETE FILE"""
        index_dict = {1: self._cmd.lchan.selected_file.get_selectable_names()}
        return self._cmd.index_based_complete(text, line, begidx, endidx, index_dict=index_dict)

    termdf_parser = argparse.ArgumentParser()
    termdf_parser.add_argument('--force', action='store_true',
            help='I really want to terminate the file. I know I can not recover from it!')
    termdf_parser.add_argument('NAME', type=str, help='File name or FID')

    @cmd2.with_argparser(termdf_parser)
    def do_terminate_df(self, opts):
        """Terminate the specified DF. DANGEROUS!  See TS 102 222 6.7.
        This is a permanent, one-way operation on the card. There is no undo, you can not recover
        a terminated DF.  The only permitted command for a terminated DF is the DLETE FILE command."""
        if not opts.force:
            self._cmd.perror("Refusing to terminate the file, please read the help text.")
            return
        f = self._cmd.lchan.get_file_for_selectable(opts.NAME)
        (data, sw) = self._cmd.card._scc.terminate_df(f.fid)

    def complete_terminate_df(self, text, line, begidx, endidx) -> List[str]:
        """Command Line tab completion for TERMINATE DF"""
        index_dict = {1: self._cmd.lchan.selected_file.get_selectable_names()}
        return self._cmd.index_based_complete(text, line, begidx, endidx, index_dict=index_dict)

    @cmd2.with_argparser(termdf_parser)
    def do_terminate_ef(self, opts):
        """Terminate the specified EF. DANGEROUS!  See TS 102 222 6.8.
        This is a permanent, one-way operation on the card. There is no undo, you can not recover
        a terminated EF.  The only permitted command for a terminated EF is the DLETE FILE command."""
        if not opts.force:
            self._cmd.perror("Refusing to terminate the file, please read the help text.")
            return
        f = self._cmd.lchan.get_file_for_selectable(opts.NAME)
        (data, sw) = self._cmd.card._scc.terminate_ef(f.fid)

    def complete_terminate_ef(self, text, line, begidx, endidx) -> List[str]:
        """Command Line tab completion for TERMINATE EF"""
        index_dict = {1: self._cmd.lchan.selected_file.get_selectable_names()}
        return self._cmd.index_based_complete(text, line, begidx, endidx, index_dict=index_dict)

    tcard_parser = argparse.ArgumentParser()
    tcard_parser.add_argument('--force-terminate-card', action='store_true',
            help='I really want to permanently terminate the card. It will not be usable afterwards!')

    @cmd2.with_argparser(tcard_parser)
    def do_terminate_card_usage(self, opts):
        """Terminate the Card. SUPER DANGEROUS!  See TS 102 222 Section 6.9.
        This will permanently brick the card and can NOT be recovered from!"""
        if not opts.force_terminate_card:
            self._cmd.perror("Refusing to permanently terminate the card, please read the help text.")
            return
        (data, sw) = self._cmd.card._scc.terminate_card_usage()

    create_parser = argparse.ArgumentParser()
    create_parser.add_argument('FILE_ID', type=str, help='File Identifier as 4-character hex string')
    create_parser._action_groups.pop()
    create_required = create_parser.add_argument_group('required arguments')
    create_optional = create_parser.add_argument_group('optional arguments')
    create_required.add_argument('--ef-arr-file-id', required=True, type=str, help='Referenced Security: File Identifier of EF.ARR')
    create_required.add_argument('--ef-arr-record-nr', required=True, type=int, help='Referenced Security: Record Number within EF.ARR')
    create_required.add_argument('--file-size', required=True, type=int, help='Size of file in octets')
    create_required.add_argument('--structure', required=True, type=str, choices=['transparent', 'linear_fixed', 'ber_tlv'],
                                 help='Structure of the to-be-created EF')
    create_optional.add_argument('--short-file-id', type=str, help='Short File Identifier as 2-digit hex string')
    create_optional.add_argument('--shareable', action='store_true', help='Should the file be shareable?')
    create_optional.add_argument('--record-length', type=int, help='Length of each record in octets')

    @cmd2.with_argparser(create_parser)
    def do_create_ef(self, opts):
        """Create a new EF below the currently selected DF.  Requires related privileges."""
        file_descriptor = {
            'file_descriptor_byte': {
                'shareable': opts.shareable,
                'file_type': 'working_ef',
                'structure': opts.structure,
            }
        }
        if opts.structure == 'linear_fixed':
            if not opts.record_length:
                self._cmd.perror("you must specify the --record-length for linear fixed EF")
                return
            file_descriptor['record_len'] = opts.record_length
            file_descriptor['num_of_rec'] = opts.file_size // opts.record_length
            if file_descriptor['num_of_rec'] * file_descriptor['record_len'] != opts.file_size:
                raise ValueError("File size not evenly divisible by record length")
        elif opts.structure == 'ber_tlv':
            self._cmd.perror("BER-TLV creation not yet fully supported, sorry")
            return
        ies = [FileDescriptor(decoded=file_descriptor), FileIdentifier(decoded=opts.FILE_ID),
               LifeCycleStatusInteger(decoded='operational_activated'),
               SecurityAttribReferenced(decoded={'ef_arr_file_id': opts.ef_arr_file_id,
                                                 'ef_arr_record_nr': opts.ef_arr_record_nr }),
               FileSize(decoded=opts.file_size),
               ShortFileIdentifier(decoded=opts.short_file_id),
            ]
        fcp = FcpTemplate(children=ies)
        (data, sw) = self._cmd.card._scc.create_file(b2h(fcp.to_tlv()))
        # the newly-created file is automatically selected but our runtime state knows nothing of it
        self._cmd.lchan.select_file(self._cmd.lchan.selected_file)

    createdf_parser = argparse.ArgumentParser()
    createdf_parser.add_argument('FILE_ID', type=str, help='File Identifier as 4-character hex string')
    createdf_parser._action_groups.pop()
    createdf_required = createdf_parser.add_argument_group('required arguments')
    createdf_optional = createdf_parser.add_argument_group('optional arguments')
    createdf_sja_optional = createdf_parser.add_argument_group('sysmoISIM-SJA optional arguments')
    createdf_required.add_argument('--ef-arr-file-id', required=True, type=str, help='Referenced Security: File Identifier of EF.ARR')
    createdf_required.add_argument('--ef-arr-record-nr', required=True, type=int, help='Referenced Security: Record Number within EF.ARR')
    createdf_optional.add_argument('--shareable', action='store_true', help='Should the file be shareable?')
    createdf_optional.add_argument('--aid', type=str, help='Application ID (creates an ADF, instead of a DF)')
    # mandatory by spec, but ignored by several OS, so don't force the user
    createdf_optional.add_argument('--total-file-size', type=int, help='Physical memory allocated for DF/ADi in octets')
    createdf_sja_optional.add_argument('--permit-rfm-create', action='store_true')
    createdf_sja_optional.add_argument('--permit-rfm-delete-terminate', action='store_true')
    createdf_sja_optional.add_argument('--permit-other-applet-create', action='store_true')
    createdf_sja_optional.add_argument('--permit-other-applet-delete-terminate', action='store_true')

    @cmd2.with_argparser(createdf_parser)
    def do_create_df(self, opts):
        """Create a new DF below the currently selected DF.  Requires related privileges."""
        file_descriptor = {
            'file_descriptor_byte': {
                'shareable': opts.shareable,
                'file_type': 'df',
                'structure': 'no_info_given',
            }
        }
        ies = []
        ies.append(FileDescriptor(decoded=file_descriptor))
        ies.append(FileIdentifier(decoded=opts.FILE_ID))
        if opts.aid:
            ies.append(DfName(decoded=opts.aid))
        ies.append(LifeCycleStatusInteger(decoded='operational_activated'))
        ies.append(SecurityAttribReferenced(decoded={'ef_arr_file_id': opts.ef_arr_file_id,
                                                     'ef_arr_record_nr': opts.ef_arr_record_nr }))
        if opts.total_file_size:
            ies.append(TotalFileSize(decoded=opts.total_file_size))
        # TODO: Spec states PIN Status Template DO is mandatory
        if opts.permit_rfm_create or opts.permit_rfm_delete_terminate or opts.permit_other_applet_create or opts.permit_other_applet_delete_terminate:
               toolkit_ac = {
                   'rfm_create': opts.permit_rfm_create,
                   'rfm_delete_terminate': opts.permit_rfm_delete_terminate,
                   'other_applet_create': opts.permit_other_applet_create,
                   'other_applet_delete_terminate': opts.permit_other_applet_delete_terminate,
                   }
               ies.append(ProprietaryInformation(children=[ToolkitAccessConditions(decoded=toolkit_ac)]))
        fcp = FcpTemplate(children=ies)
        (data, sw) = self._cmd.card._scc.create_file(b2h(fcp.to_tlv()))
        # the newly-created file is automatically selected but our runtime state knows nothing of it
        self._cmd.lchan.select_file(self._cmd.lchan.selected_file)

    resize_ef_parser = argparse.ArgumentParser()
    resize_ef_parser.add_argument('NAME', type=str, help='Name or FID of file to be resized')
    resize_ef_parser._action_groups.pop()
    resize_ef_required = resize_ef_parser.add_argument_group('required arguments')
    resize_ef_required.add_argument('--file-size', required=True, type=int, help='Size of file in octets')

    @cmd2.with_argparser(resize_ef_parser)
    def do_resize_ef(self, opts):
        """Resize an existing EF below the currently selected DF.  Requires related privileges."""
        f = self._cmd.lchan.get_file_for_selectable(opts.NAME)
        ies = [FileIdentifier(decoded=f.fid),
               FileSize(decoded=opts.file_size)]
        fcp = FcpTemplate(children=ies)
        (data, sw) = self._cmd.card._scc.resize_file(b2h(fcp.to_tlv()))
        # the resized file is automatically selected but our runtime state knows nothing of it
        self._cmd.lchan.select_file(self._cmd.lchan.selected_file)

    def complete_resize_ef(self, text, line, begidx, endidx) -> List[str]:
        """Command Line tab completion for RESIZE EF"""
        index_dict = {1: self._cmd.lchan.selected_file.get_selectable_names()}
        return self._cmd.index_based_complete(text, line, begidx, endidx, index_dict=index_dict)
