#!/usr/bin/env python

#    This file is part of Diamond.
#
#    Diamond 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 3 of the License, or
#    (at your option) any later version.
#
#    Diamond 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 Diamond.  If not, see <http://www.gnu.org/licenses/>.

import getopt
import os
import os.path
import sys
import traceback
import string

import gtk
import gtk.gdk
gtk.gdk.threads_init()
import gobject
gobject.threads_init()

# do this right at the start, so we can find the diamond modules
diamond_path = os.path.join( os.path.realpath(os.path.dirname(__file__)), os.pardir )
sys.path.insert(0, diamond_path)
dxdiff_path = os.path.join( os.path.realpath(os.path.dirname(__file__)), os.pardir, os.pardir, "dxdiff" )
sys.path.insert(0, dxdiff_path)

import diamond.debug as debug

def Help():
  """
  Prints usage information to standard output.
  """

  debug.dprint("Usage: diamond [OPTIONS] ... [FILE]\n" + \
               "\n" + \
               "A Relax NG aware XML editor. [FILE] is the XML file to be opened (a new file is\n" + \
               "created if this is not supplied).\n" + \
               "\n" + \
               "Options:\n" + \
               "\n" + \
               "-h               Display this message\n" + \
               "-f               Forks at startup\n" + \
               "-s [SCHEMAFILE]  Use the supplied schema file *\n" + \
               "-a [ALIAS]       Use the supplied alias, if not given use \"default\"\n" + \
               "-t [TRONFILE]    Use the supplied schematron file for extended validation\n" + \
               "-d [FILE]        Diff against the supplied file. (FILE must be specified)\n" + \
               "-u [DIRECTORY]   Find unused schema entries in the given directory\n" + \
               "--ub [DIRECTORY] Find unused schema entries, batch mode\n" + \
               "-v               Verbosity switch - if supplied Diamond prints additional\n" + \
               "                 debugging information to standard output and standard error\n" + \
               "\n" + \
               "* Note: The locations of Spud schemas can also be defined in various schemata folders,\n" + \
               "  see the Spud manual for further details.", 0)

  return

def main():

  try:
    opts, args = getopt.gnu_getopt(sys.argv[1:], "hvfs:a:t:d:u:", ["ub="])
  except:
    Help()
    sys.exit(1)

  if len(args) > 1:
    Help()
    sys.exit(1)

  if not ("-v", "") in opts:
    debug.SetDebugLevel(0)
  if ("-h", "") in opts:
    Help()
    return
  if ("-f", "") in opts:
    # Detach from controlling terminal
    try:
      pid = os.fork()
      if pid == 0:
        os.setsid()
        pid = os.fork()
        if pid != 0:
          os._exit(0)
      else:
        os._exit(0)
    except:
      pass

  import diamond.config as config
  import diamond.dialogs as dialogs
  import diamond.interface as interface
  import diamond.schemausage as schemausage
  import diamond.schema as schema
  import diamond.tree as tree
  import diamond.plugins as plugins
  import diamond.useview as useview

  try:
    input_filename = args[0]
  except IndexError:
    input_filename = None

  logofile = None
  for possible_logofile in [os.path.join(diamond_path, "gui", "diamond.svg"), 
                            "/usr/share/diamond/gui/diamond.svg",
                            os.path.join(diamond_path, "gui", "diamond.png"),]:
    try:
      os.stat(possible_logofile)
      if logofile == None:
        logofile = []
      logofile.append(possible_logofile)
    except OSError:
      pass


  # Let's find a schema.

  suffix = "xml"

  # if the user specifies a schema on the command line, use that.

  input_schemafile = None
  input_alias = None
  input_schematron_file = None
  for opt in opts:
    if opt[0] == "-s":
      input_schemafile = opt[1]
    elif opt[0] == "-a":
      input_alias = opt[1]    
    elif opt[0] == "-t":
      input_schematron_file = opt[1]

  if input_schemafile is not None and input_alias is not None:
    debug.deprint("-s and -a are mutually exclusive", 0)
    sys.exit(1)

  #schemafile is not given so look up actual path
  if input_schemafile is None:

    # if the user has specified a file to work on, use the suffix as a key
    if input_filename is not None:
      suffix = input_filename.split(".")[-1]
      try:
        schemata = config.schemata[suffix]
      except:
        debug.deprint("Could not find schema matching suffix %s." % suffix, 0)
        debug.deprint("Have you registered it in /usr/share/diamond/schemata, /etc/diamond/schemata, $HOME/.diamond/schemata", 0)
        debug.deprint("or a schemata directory beneath a location listed in the environment variable $DIAMOND_CONFIG_PATH?", 0)
        debug.deprint("To register a schema, place a file in one of those directories, and let its name be the suffix of your language.", 0)
        debug.deprint("The file should consist of:", 0)
        debug.deprint(" A Verbal Description Of The Language Purpose", 0)
        debug.deprint(" alias1=/path/to/schema1/file.rng", 0)
        debug.deprint(" alias2=/path/to/schema2/file.rng", 0)
        sys.exit(1)
      
    elif len(config.schemata) == 0:
      debug.deprint("Could not find a schema file.", 0)
      debug.deprint("Have you registered it in /usr/share/diamond/schemata, /etc/diamond/schemata, $HOME/.diamond/schemata", 0)
      debug.deprint("or a schemata directory beneath a location listed in the environment variable $DIAMOND_CONFIG_PATH?", 0)
      debug.deprint("To register a schema, place a file in one of those directories, and let its name be the suffix of your language.", 0)
      debug.deprint("The file should consist of:", 0)
      debug.deprint(" A Verbal Description Of The Language Purpose", 0)
      debug.deprint(" alias1=/path/to/schema1/file.rng", 0)
      debug.deprint(" alias2=/path/to/schema2/file.rng", 0)
      sys.exit(1)

    # if there is only one schema, use that
    elif len(config.schemata) == 1:
      suffix = config.schemata.keys()[0]
      schemata = config.schemata[suffix]
    
    # otherwise ask the user to choose
    else:
      choices = [key + ": " + value[0] for key, value in config.schemata.iteritems()]
      choice = dialogs.radio_dialog("Choose a schema", "Choose a schema to use:", choices, logofile[0])
      suffix = choice.split(":")[0]
      schemata = config.schemata[suffix]

    try:
      #if input_alias is None it will just use the default
      input_schemafile = schemata[1][input_alias]
    except KeyError:
      debug.deprint("""Could not find alias "%s"!""" % (input_alias or "default"), 0)
      sys.exit(1)

  #endif

  # ensure that the specified schema actually exists!
  try:
    if 'http' not in input_schemafile:
      os.stat(input_schemafile)
  except OSError:
    debug.deprint("Could not find schemafile %s!" % input_schemafile, 0)
    sys.exit(1)

  if input_schematron_file is not None:
    # ensure that the specified schematron file actually exists!
    try:
      os.stat(input_schematron_file)
    except OSError:
      debug.deprint("Could not find Schematron file %s!" % input_schematron_file, 0)
      sys.exit(1)

  if input_filename is not None:
    try:
      os.stat(input_filename)
    except OSError:
       pass

  # Import the GUI Glade file.

  gladefile = None
  for possible_gladefile in [os.path.join(diamond_path, "gui", "gui.glade"),
                             os.path.join(diamond_path, "share", "diamond", "gui", "gui.glade"),
                             "/usr/share/diamond/gui/gui.glade"]:
    try:
      os.stat(possible_gladefile)
      gladefile = possible_gladefile
      break
    except OSError:
      pass
  if gladefile is None:
    debug.deprint("Cannot locate GUI!", 0)
    sys.exit(1)

  # If input_schemafile doesn't exist, use the fluidity_options schema.
  if input_schemafile is None:
    debug.deprint("Cannot locate schemafile!", 0)
    sys.exit(1)

  debug.dprint("\n" + \
               "Glade file:  " + str(gladefile) + "\n" + \
               "Schema file: " + str(input_schemafile) + "\n" + \
               "Logo file:   " + str(logofile) + "\n" + \
               "Input file:  " + str(input_filename) + "\n")

  # see if the user wants to find usage
  input_usage = None
  input_usagebatch = None
  for opt in opts:
    if opt[0] == "-u":
      input_usage = opt[1]
    if opt[0] == "--ub":
      input_usagebatch = opt[1]

  if input_usagebatch:
    paths = []
    for dirpath, dirnames, filenames in os.walk(input_usagebatch):
      paths.extend([os.path.join(dirpath, filename) for filename in filenames if filename.endswith(suffix)])

    unused = schemausage.find_unusedset(schema.Schema(input_schemafile), paths)

    for xpath in unused:
      print xpath

    if unused:
      return 1
    else:
      return 0

  elif input_usage:
    view = useview.UseView(schema.Schema(input_schemafile), suffix, input_usage)
    view.connect("delete_event", lambda widget, event: gtk.main_quit())
  else:
    plugins.configure_plugins(suffix)

    try:
      i = interface.Diamond(gladefile = gladefile, logofile = logofile, suffix = suffix)
    except Exception, e:
      debug.deprint('Error: ' + str(e), 0)
      i = interface.Diamond(gladefile = gladefile, suffix = suffix)

    i.main_window.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH))
    i.open_file(schemafile = input_schemafile, filename = input_filename)
    i.main_window.window.set_cursor(None)

    # see if the user wants to diff against a file
    input_difffile = None
    for opt in opts:
      if opt[0] == "-d":
        input_difffile = opt[1]

    if input_difffile:
      if input_filename:
        i.on_diff(None, input_difffile)
      else:
        debug.dprint("Cannot diff if against nothing.", 0)
  #endif

  gtk.main()

  return

if __name__ == "__main__":
#  import hotshot
#  prof = hotshot.Profile("hotshot_stats.prof")
#  prof.runcall(main)
#  prof.close()
  sys.exit(main())
