#!/usr/bin/env python
# Copyright (c) 2007-2011 Arastra, Inc.  All rights reserved.
# Arastra, Inc. Confidential and Proprietary.

# Generate a prefdl to stdout or a file, taking input from stdin
# Decode a prefdl to stdout, taking input from stdin or a file

import sys, argparse
import Prefdl

usage = """prefdl [args] <filename>

  Generate a prefdl to stdout or a file, taking input from stdin

  Prompt the user to enter the prefdl information on stdin and generate
  a prefdl to <filename> in proper compressed format.  If stdin is not a
  tty, then prefdl chooses quiet operation, and does not generate any
  output to stdout (unless - is selected as the outfile)

prefdl [args] --decode <filename>

  Decode a prefdl to stdout, taking input from stdin or a file
  and generating decoded output to stdout.  Exit code is 1 if
  the prefdl appears invalid

Spaces are ignored when inputting data.
Readline-style line editing and history is supported.
Up to 20 deviations are allowed.

If "-" is specified as <filename>, then stdout (or stdin) is used
-q forces quiet operation.


"""

parser = argparse.ArgumentParser(usage=usage)
parser.add_argument( 'filename' )
parser.add_argument( "-q", "--quiet", action="store_true",
                   help="generate no output. (except fdl, possibly)" )
parser.add_argument( "-d", "--decode", action="store_true",
                   help="decode a prefdl, rather than generating one. "
                   "Pass '-' to specify stdin as the source." )
parser.add_argument( "-e", "--encode", action="store_true",
                   help="Encode a prefdl from an input file. "
                   "Pass '-' to specify stdin as the source." )
parser.add_argument( "-o", "--output", dest="output_file", 
                   help="Set an output file. "
                   "Defaults to stdout if not specified." )
parser.add_argument( "-f", "--force", action="store_true",
                   help="Ignore an invalid CRC when decoding." )
parser.add_argument( "--swFeatures", action="store",
                   help="Provide a dict for SW defined features" )
parser.add_argument( "--signatureList", action="store",
                   help="Provide list of prefdl variables in signature" )
parser.add_argument( "--certificate", action="store", help="Provide certificate" )
parser.add_argument( "--signature", action="store", help="Provide signature" )
parser.add_argument( "--ztpToken", action="store",
                     help="Provide JWT token to validate the switch in SecureZTP" )
parser.add_argument( "-u", "--usedefault", action = "store_true",
                    help="Use defaults from a file created by reading an idprom "\
                    "and write to that file.")
parser.add_argument( "-r", "--remove", action="store_true",
                   help="Remove options attribute from prefdl." )

Prefdl.add_prefdl_args( parser )

args = parser.parse_args()

if args.force and not args.decode:
   parser.error( "--force option can only be used with --decode" )


if args.output_file and ( args.usedefault or args.remove ):
   parser.error( "--output option cannot be used with --usedefault or --remove" )

if args.decode and ( args.pca or args.sn or args.sku or
                        args.kvn or args.deviations ):
   parser.error( "Cannot specify dut descriptions or the command line "
                 "with the --decode option" )

output = args.filename

args.quiet = args.quiet or not sys.stdin.isatty()

def askfor( question, validate, what, isOptional ):
   
   if args.quiet:
      while True:
         line = sys.stdin.readline()[:-1]
         if not line.startswith( "#" ): 
            break
      if isOptional and line == '': 
         return ''
      ans = validate( line )
      if ans is None:
         sys.stderr.write( "Invalid input for %s: '%s'\n" % (what, ans ) )
         raise ValueError
   else:
      import readline
      while True:
         line = raw_input( question + " ")
         if isOptional and  line == '' : 
            return ''
         ans = validate( line )
         if ans is not None: 
            break
         print "Invalid format, try again"
   return ans

def exitError( e ):
   sys.stderr.write( "%s\n" % e )
   sys.exit( 1 )

def main():
   if args.decode:
      if output == "-":
         fp = sys.stdin
      else:
         fp = file( output, "r" )
      try:
         sys.stdout.write( Prefdl.decode( fp, **vars( args ) ) )
      except ( Prefdl.InvalidData, IndexError, RuntimeError ) as e:
         exitError( e )

   elif args.encode:
      if output == "-":
         fpIn = sys.stdin
      else:
         fpIn = file( output, "r" )
      
      if args.output_file:
         fpOut = file( args.output_file, "w+" )
      else:
         fpOut = sys.stdout
      try:
         Prefdl.encode( fpIn, fpOut )
      except ValueError as e:
         exitError( e )   
      
   else:
      try:
         askfunc = askfor if sys.stdin.isatty() else None
         Prefdl.generate( output, askfunc, **vars( args ) )
      except ( Prefdl.InvalidData, ValueError ) as e:
         exitError( e )

if __name__ == "__main__":
   main()
