# takes: fei (either xml or text) and smv,
# and produces smv and fault modes files

import sys
import os.path
import logging
import subprocess

import _paths
import _utils


# WARNING! ordering is important here!
FT_ENGINES = "bdd bmc bddbmc msat ic3".split()
(FT_ENGINE_BDD,
 FT_ENGINE_BMC,
 FT_ENGINE_BDD_BMC,
 FT_ENGINE_MSAT,
 FT_ENGINE_IC3, ) = FT_ENGINES



def handle_options():
    """returns (options, input_file):
    values (as a map) and the name of the input file"""

    import argparse
    parser = argparse.ArgumentParser(description="Produces an extend smv file"
                                     " out of given nominal smv file and fei")

    parser.add_argument("--smv-file",
                        metavar="SMV-FILE",
                        help="The input extended smv file name")

    parser.add_argument("--fms-file",
                        metavar="FMS-FILE",
                        help="The input fault mode xml file name")

    parser.add_argument("--faults-bound", "-N",
                        type=int,
                        metavar="BOUND",
                        help="Sets a bound to the maximum number of faults")

    parser.add_argument("--prop-index", "-n",
                        type=int,
                        metavar="INDEX",
                        help="Property index to be used as TLE")

    parser.add_argument("--prop-name", "-P",
                        metavar="NAME",
                        help="Property name to be used as TLE")

    parser.add_argument("--prop-text", "-p",
                        metavar="PROPERTY",
                        help="Textual property to be used as TLE")

    parser.add_argument('--verbose', '-v',
                        action='store_true',
                        default=False,
                        help='Sets verbosity to high level')

    parser.add_argument('--engine', '-E',
                        choices=FT_ENGINES,
                        default=FT_ENGINE_BDD,
                        help='Use given engine (default: %(default)s)')

    parser.add_argument('--dynamic',
                        action='store_true',
                        default=False,
                        help='Generates dynamic fault tree')

    parser.add_argument('--gen-trace', "-e",
                        action='store_true',
                        default=False,
                        help='Generates xml trace from fault tree')

    parser.add_argument('--bmc-length', "-k",
                        type=int,
                        default=10,
                        help='Specify BMC length (integer)')

    parser.add_argument('--show', '-s',
                        action='store_true',
                        default=False,
                        help='Show the generated fault tree')

    parser.add_argument("--probability",
                        action='store_true',
                        default=False,
                        help="Computes probability when generating FT")

    parser.add_argument("--symbolic", '-S',
                        action='store_true',
                        default=False,
                        help="Generates symbolic probability as well "
                        "when computing probability",)

    parser.add_argument("--quick", '-Q',
                        action='store_true',
                        default=False,
                        help="For quick computation, avoid ordering the "
                        "FT and when computing probability avoid computing"
                        "probability of intermediate nodes. Use to"
                        "speedup computation.",)

    parser.add_argument(
        "-d", "--outdir",
        default="out",
        metavar="PATH",
        help="Output directory, where all generated file should be "
        "put into (default:%(default)s)")

    args = parser.parse_args()

    for fn in (args.smv_file, args.fms_file):
        if fn and not os.path.isfile(fn):
            parser.error("File not found: " + fn)

    if os.path.exists(args.outdir) and not os.path.isdir(args.outdir):
        parser.error("Not a directory: " + args.outdir)

    prop = [p for p in (args.prop_index, args.prop_name, args.prop_text)
            if p is not None]
    if len(prop) > 1:
        parser.error("Only one property can be specified")

    if args.symbolic and not args.probability:
        parser.error("Option -S (--symbolic) requires --probability")

    return args


if "__main__" == __name__:

    _paths.setup_path()

    import xsap.utils.misc.log
    from xsap.utils.processes.xsap_process import XsapProcess
    xsap.utils.misc.log.init()

    opts = handle_options()

    if not os.path.exists(opts.outdir):
        os.makedirs(opts.outdir)

    if opts.verbose:
        logging.getLogger().setLevel(logging.INFO)


    # automatically searches for inputs when not explicitly provided
    smv_fname = _utils.get_suitable_smv_file(opts.smv_file, opts.outdir)
    if smv_fname is None:
        sys.exit(1)

    fms_fname = _utils.get_suitable_fms_file(opts.fms_file,
                                             smv_fname,
                                             opts.outdir)
    if fms_fname is None:
        sys.exit(1)

    stdouterr_fname = os.path.join(opts.outdir, "xsap_compute_ft.out")
    if os.path.exists(stdouterr_fname):
        os.remove(stdouterr_fname)

    stdouterr_file = open(stdouterr_fname, "w")

    # instantiate the process
    logging.info("Invoking xsap to compute fault tree")

    need_msat = XsapProcess.has_infinite_domain_vars(smv_fname) or opts.engine == FT_ENGINE_MSAT
    with  XsapProcess(smv_fname, fms_fname,
                      ord_fname=None, need_msat=need_msat,
                      args=["-v", "%d" % (5 if opts.verbose else 0)],
                      stdout=subprocess.PIPE,
                      stderr=subprocess.STDOUT,
                      dumpers=[stdouterr_file]) as xsap_process:

        # set the prefix
        full_base, _ext = os.path.splitext(smv_fname)
        base = os.path.basename(full_base)
        xsap_process.set_tmp_filename_prefix(opts.outdir + "/" + base)

        stdouterr_file.write("\n" + "-" * 70)
        stdouterr_file.write("\nInvoking: %s %s\n" % (xsap_process.get_path(),
                                                  " ".join(xsap_process.get_args())))
        stdouterr_file.write("\n" + "-" * 70)
        stdouterr_file.write("\n")

        prop = (('-n %d' % opts.prop_index) if opts.prop_index is not None
                else
                ('-P "%s"' % opts.prop_name) if opts.prop_name is not None
                else
                ('"%s"' % opts.prop_text) if opts.prop_text is not None
                else "")

        ev_file, gates_file, xml_file = xsap_process.compute_fault_tree(
            prop, opts.dynamic, opts.bmc_length,
            use_bdd=opts.engine==FT_ENGINE_BDD,
            use_bdd_bmc=opts.engine==FT_ENGINE_BDD_BMC,
            compute_probabilities=opts.probability,
            use_param=opts.engine==FT_ENGINE_IC3,
            fails_nbr=opts.faults_bound,
            symbolic=opts.symbolic,
            quick=opts.quick,
            gen_trace=opts.gen_trace,
            gen_random_prefix=False)

    stdouterr_file.close()

    logging.info("xsap produced fault tree in: ")
    logging.info("  events: '%s'" % ev_file)
    logging.info("  gates: '%s'" % gates_file)

    if ev_file is not None and gates_file is not None and opts.show:
        logging.info("Now showing result fault tree")
        import fault_tree_viewer.ftv as ftv
        ftv.run(ev_file, gates_file, xml_file, None, None)
