#!/usr/bin/env python3
import argparse
import json
import logging
import os
import sys
sys.path.append(os.path.join(os.path.dirname(__file__), os.pardir))

from saml2.metadata import entity_descriptor
from saml2.server import Server
from spid_sp_test.metadata import SpidSpMetadataCheck
from spid_sp_test.metadata_extra import SpidSpMetadataCheckExtra
from spid_sp_test.authn_request import SpidSpAuthnReqCheck
from spid_sp_test.authn_request_extra import SpidSpAuthnReqCheckExtra

logger = logging.getLogger(__name__)


def selective_run(obj, meth_list):
    if meth_list:
        for method in meth_list:
            meth = getattr(obj, method, None)
            if meth: 
                meth()
    else:
        obj.test_all()


if __name__ == '__main__':
    _desc = (f'{__file__} -h for help')
    _epilog = f"""examples:
        {__file__} -metadata_url http://localhost:8000/spid/metadata --extra
        {__file__} -metadata_url file://metadata.xml
        {__file__} -metadata_url http://localhost:8000/spid/metadata -l test_Organization test_Signature
        {__file__} --idp-metadata
        {__file__} -metadata_url http://localhost:8000/spid/metadata --authn-url http://localhost:8000/spid/login/?idp=spid-idp-test
        {__file__} -metadata_url http://localhost:8000/spid/metadata --authn-url http://localhost:8000/spid/login/?idp=http://localhost:8080 --extra -debug ERROR -json -l xsd_check


    """
    
    parser = argparse.ArgumentParser(
                        description = _desc, 
                        epilog = _epilog,
                        formatter_class = argparse.RawTextHelpFormatter
    )
    parser.add_argument('-metadata_url', required=False, default=None,
                        help=("URL where SAML2 Metadata resides: "
                              "it can be file://path or https://fqdn"))
    parser.add_argument('--idp-metadata', 
                        action="store_true", default=False,
                        help="get example IdP metadata")
    parser.add_argument('-l','--list', nargs='*', 
                        help='esecute only selected checks', 
                        required=False)
    parser.add_argument('--extra', 
                        action="store_true", default=False,
                        help="execute extra checks")
    
    parser.add_argument('--authn-url', required=False, default=None,
                        help=("URL where the SP initializes "
                              "the Authentication Request to this IDP,"
                              "it can also be a file:///"))

    parser.add_argument('-json', action="store_true", 
                        help="json output")

    parser.add_argument('-o', required=False, 
                        help="json output to file")

    parser.add_argument('-debug', required=False, 
                    choices=('CRITICAL', 'ERROR', 
                             'WARNING', 'INFO', 'DEBUG'), 
                    default='INFO',
                    help="Debug level, see python logging")
    args = parser.parse_args()
    
    logging.basicConfig(level=getattr(logging, args.debug))
    
    if len(sys.argv)==1:
        parser.print_help(sys.stderr)
        sys.exit(1)
    
    tests_done = []
    
    if args.idp_metadata:
        from spid_sp_test.idp.idp import SAML2_IDP_CONFIG
        
        idp_server = Server(SAML2_IDP_CONFIG)
        idp_metadata = entity_descriptor(idp_server.config)
        print(idp_metadata.to_string().decode())
        sys.exit(0)
    
    elif args.metadata_url:
        data_md = dict(metadata_url = args.metadata_url)
        metadata_check = SpidSpMetadataCheck(**data_md)
        selective_run(metadata_check, args.list)
        tests_done.append(metadata_check)
        if args.extra:
            metadata_check_extra = SpidSpMetadataCheckExtra(**data_md)
            selective_run(metadata_check_extra, args.list)
            tests_done.append(metadata_check_extra)

    else:
        logging.error('At least --id-metadata or --metadata-url is needed!')
        sys.exit(1)

    # authn request
    if args.authn_url:
        data_ac = dict(
            metadata = metadata_check.metadata,
            authn_request_url = args.authn_url
        )
        authn_check = SpidSpAuthnReqCheck(**data_ac)
        selective_run(authn_check, args.list)
        tests_done.append(authn_check)

        if args.extra:
            authn_check_extra = SpidSpAuthnReqCheckExtra(**data_ac)
            selective_run(authn_check_extra, args.list)
            tests_done.append(authn_check_extra)

    # OUTPUT - REPORT
    if args.o or args.json:
        data = {
          "test": {
            "sp": {}
            }
        }
        
        for i in tests_done:
            data['test']['sp'][i.category] = i.report_to_dict()[i.category]
        
        output = json.dumps(data, indent=2)
        
        if args.json:
            print(output)
        
        if args.o:
            with open(args.o, 'w') as f:
                f.write(output)
    
