#!/usr/bin/env python3
##############################################################################
#
# Copyright (c) 2003-2018 by The University of Queensland
# http://www.uq.edu.au
#
# Primary Business: Queensland, Australia
# Licensed under the Apache License, version 2.0
# http://www.apache.org/licenses/LICENSE-2.0
#
# Development until 2012 by Earth Systems Science Computational Center (ESSCC)
# Development 2012-2013 by School of Earth Sciences
# Development from 2014 by Centre for Geoscience Computing (GeoComp)
#
##############################################################################

from __future__ import division, print_function

import os
import inspect
import importlib
import sys

if len(sys.argv)!=4:
  sys.stderr.write('Usage: startdir startpackage outputdirectory\n')
  sys.exit(1)

#startdir='./esys'
#startpackage='esys'
#outdir='doctest'

pathdir=sys.argv[1]
startpackage=sys.argv[2]
startdir=os.path.join(pathdir, startpackage)
outdir=sys.argv[3]

def dumpPackage(mname, ignorelist, modset, banset):
  try:
    print(mname)
    PP=importlib.import_module(mname)
  except ImportError as ie:
    print("Import error for "+mname+"  "+str(ie))
    exit(1)
  nonempty = False
  for x in dir(PP):
      if not x.startswith("__"):
          nonempty = True
          break
  if not nonempty:
      print("Package is empty")
      return
  modset.add(mname)
  print("Starting dump on "+mname+' with ignore at '+str(ignorelist))
  pack=open(os.path.join(outdir,mname+'.rst'),'w')
  pack.write(mname+' Package\n')
  pack.write('='*len(mname)+'========\n\n')
#  pack.write('.. py:module:: '+mname+'\n\n')
  moddoc = inspect.getdoc(PP)
  if not moddoc:
     moddoc = "-"
  pack.write(".. module:: %s\n   :synopsis: %s\n"%(mname, "".join(moddoc.replace("\n\n", "\n").replace("\n", " "))))
  pack.write("\n"+moddoc+"\n")
  #Automodule does not seem to do what we want so we need to drill down
  clist=[]
  flist=[]
  vlist=[]
  modlist=[]
  norecurse=[]
  try:
    norecurse=PP.__nodocorecursion
    print("Supressing the following packages")
    for n in norecurse:
      print(mname+'.'+n)
      banset.add(mname+'.'+n)
    print('---------')
  except AttributeError:
    pass
  # esys.escript.models does not get picked up by this loop
  for (name, mem) in inspect.getmembers(PP):
      print("    "+name)
      if name.startswith("__"):
          continue
      if "__module__" in dir(mem) and mem.__module__=='__future__':
          continue
      if inspect.ismodule(mem):
        if not name in ignorelist:
           try:
             ppfile=inspect.getfile(PP)
             memfile=inspect.getfile(mem)
           except:
             continue    #It will be a builtin module
           ppdir=ppfile[:ppfile.rfind(os.path.sep)]
           memdir=memfile[:memfile.rfind(os.path.sep)]
           if ppdir==memdir:
              if not mem.__name__ in modset:
                if not mem.__name__ in banset:
                  print("About to dump "+name+"("+mem.__name__+")")
                  dumpPackage(mem.__name__, [], modset, banset)
                  print("Dump of "+mname+" complete")
                  modlist.append(name)
        #pack.write('Module '+name+'\n')
      elif inspect.isclass(mem):
        clist+=[(name, mem)]
      elif inspect.isfunction(mem):
        flist+=[(name, mem)]
      else:
        if type(mem).__module__+'.'+type(mem).__name__=='Boost.Python.function':
          flist+=[(name, mem)]
        else:
              vlist+=[(name, mem)]
  pack.write('\nClasses\n')
  pack.write('-------\n')
  for (name, mem) in clist:
      pack.write('* `'+name+'`\n')
  pack.write('\n')
  for (name, mem) in clist:
    pack.write('.. autoclass:: '+mname+'.'+name+'\n')
    pack.write('   :members:\n   :undoc-members:\n\n   .. automethod:: __init__\n\n')
  pack.write('\n')
    
  pack.write('Functions\n')
  pack.write('---------\n')
  for (name, mem) in flist:
    pack.write('.. autofunction:: '+name+'\n')
  pack.write('\n')
    
  pack.write('Others\n')
  pack.write('------\n')
  for (name, mem) in vlist:
    pack.write('* '+name+'\n')
  pack.write('\n')
  pack.write('Packages\n')
  pack.write('--------\n')
  pack.write('.. toctree::\n\n')
  for name in modlist:
      pack.write('   '+mname+'.'+name+'\n')
  pack.write('\n')
  pack.close()

def listmods():
  W=os.walk(startdir,topdown=True)
  sys.path.append(pathdir)
  main=open(os.path.join(outdir,'index.rst'),'w')
  main.write('.. Generated by Joel\'s script\n\n')
  main.write('Documentation for esys.escript\n')
  main.write('==============================\n')
  main.write('\n')
  main.write('Contents:\n\n')
  main.write('.. toctree::\n')
  main.write('   :maxdepth: 1\n')
  main.write('\n')
  modset=set()
  banset=set()
  for z in W:
    if z[0].endswith('__pycache__'): continue
    #if z[0].find('escript')==-1: continue
    if z[0].find('escriptcore')!=-1: continue
    print("Beginning ",z[0])
    # Now make the package name
    n=startpackage+'.'.join(z[0][len(startdir):].split(os.path.sep))
    dumpPackage(n, z[1], modset, banset)
    print("-------------"+n)
    
    for m in z[2]:        #This will list the files
      if m.split('.')[1]=='pyc' and m!='__init__.pyc':
        print(".."+n+"."+m)
        print(".."+(n+'.'+m)[:-4])
        if not (n+'.'+m)[:-4] in banset:
          dumpPackage((n+'.'+m)[:-4],[],modset, banset)
  l=list(modset)
  l.sort()
  for n in l:
      if n.count(".") == 1:
         main.write("   "+n+"\n")
  main.write('\n')
  main.write('Indices and Tables\n')
  main.write('==================\n')
  main.write('\n')
  main.write('* :ref:`genindex`\n')
  main.write('* :ref:`modindex`\n')
  main.write('\n')
  main.close()
    
    
listmods()    
