/*
 * Copyright (C) 1999, 2000  Lorenzo Bettini, lorenzo.bettini@penteres.it
 *
 * This program 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 2 of the License, or
 * (at your option) any later version.
 *
 * This program 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 this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */

#include <stdio.h>
#include <string.h>
#include <iostream.h>
#include <fstream.h>

#include "version.h"
#include "main.h"
#include "colors.h"
#include "tags.h"
#include "keys.h"
#include "textgen.h"
#include "decorators.h"
#include "generators.h"
#include "messages.h"

#include "cmdline.h"
#include "copyright.h"
#include "helptext.h"

#define OUTPUT_EXTENSION ".html"

/* global symbols */

char *inputFileName, *outputFileName ; /* what we're reading  */
ostream* sout ;

int tabSpaces = 0 ;     // space to substitue to tabs

int entire_doc = 0 ; // we want a real html doc
int otherArgs ;
short verbose = 0 ;
char *cssUrl = 0 ;
int use_css = 0 ; // Use CSS instead of font-tags

char *programName = 0 ;
char *programVersion = 0 ;

extern int yylex() ;
extern int parseTags() ;

static void print_version() ;
static void print_help() ;
static void print_text( int len, char *text[] ) ; 

int main( int argc, char * argv[] ) {
  
  char *docTitle;  
  cmdline_info args_info ;     // command line structure
  int i, v; 
  
  args_info.version = 0 ;
  args_info.inputs = 0 ;
  args_info.inputs_size = 0 ;
  args_info.output = 0 ;
  args_info.input = 0 ;
  args_info.title = 0 ;
  args_info.css = 0 ;
  args_info.doc = 0 ;
  args_info.tab = 0 ;
  args_info.verbose = 0 ;
  args_info.help = 0 ;

  if((v = cmdline(argc, argv, &args_info)) != -1) 
    // calls cmdline parser. The user gived bag args if it doesn't return -1 
    return 1; 

  programName = PACKAGE ;
  programVersion = VERSION ;

  if ( args_info.version )
    {
      print_version () ;
      exit (0) ;
    }

  if ( args_info.help )
    {
      print_help () ;
      exit (0) ;
    }

  /* initialization of global symbols */
  inputFileName = outputFileName = 0 ;
  sout = 0 ;
  docTitle = 0 ;
  
  // adjust flags for command line parameters
  otherArgs = 1;

  docTitle = args_info.title ;
  verbose = args_info.verbose ;

  if ( args_info.tab > 0 )
    tabSpaces = args_info.tab ;

  cssUrl = args_info.css ;
  use_css = ( cssUrl != 0 ) ;

  entire_doc = ( args_info.doc || (docTitle != 0) || use_css ) ;
  
  inputFileName = args_info.input ;
  if ( inputFileName ) {
    outputFileName = args_info.output ;
    if ( ! outputFileName ) {
      outputFileName = createOutputFileName( inputFileName ) ;
    }
  }
  
  if ( verbose )
    setMessager( new DefaultMessages ) ;

  printMessage( PACKAGE " " VERSION ) ;
  
  parseTags() ;

  if( use_css ) {
    createGeneratorsForCSS() ;
  }
  else {
    createGenerators() ;
  }
  
  // let's start the translation :-)
  
  // first the --input file
  if ( ! args_info.inputs_size )
    processFile( inputFileName, outputFileName, docTitle ) ;

  // let's process other files, if there are any
  if ( args_info.inputs_size ) {
    for ( i = 0 ; i < (args_info.inputs_size) ; ++i ) {
      processFile( args_info.inputs[i], 
		   createOutputFileName( args_info.inputs[i] ),
		   docTitle ) ; 
      cerr << "Processed " << args_info.inputs[i] << endl ;
    }
  }
  
  return (0 );
}

// output file name = input file name + ".html"
char *createOutputFileName( char *inputFileName ) {
  char *outputFileName = new char[ strlen(inputFileName) + 
                                 strlen(OUTPUT_EXTENSION) + 1 ] ;
  strcpy( outputFileName, inputFileName ) ;
  strcat( outputFileName, OUTPUT_EXTENSION ) ;

  return outputFileName ;
}

void processFile( char *inputFileName, char *outputFileName, char *docTitle ) {
  FILE *in = 0;
  short deleteOStream = 1 ;

  if ( outputFileName ) {
    sout = new ofstream(outputFileName) ;
    if ( ! sout ) {
      cerr << "Error in creating " << outputFileName << " for output" << endl ;
      exit(1) ;
    }
  }

  if ( inputFileName ) {
      in = freopen (inputFileName, "r", stdin);
      if (!in) {
        cerr << "Error in opening " << inputFileName
             << " for input" << endl ;
        exit(1) ;
      }
  }

  /*
   * Use default values for any options not provided
   */
  if (sout == 0) {
    sout = &cout;
    deleteOStream = 0 ; // we can't delete cout !!!
  }
  if (in == 0) {
    ; /* Well stdin already points to stdin so, .... */
  }
  if (docTitle == 0) {
    docTitle = inputFileName; /* inputFileName may also be 0,
                                 this is OK. */
  }
  
  if ( entire_doc ) {
    print_top( docTitle, cssUrl );
  }

  printMessage( "translating source code... ", cerr ) ;

  generateln( "<pre>" ) ;
  generateln( "<tt>" ) ;
  yylex() ;
  generateln( "</tt>" ) ;
  generateln( "</pre>" ) ;

  printMessage( "done !", cerr ) ;
  
  if ( entire_doc )
    print_bottom() ;

  if ( deleteOStream )
    delete sout ;
}

void print_top( char *docTitle, char *cssUrl ) {
  if( cssUrl == 0 ) {
    generateln( "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML//EN\">" ) ;
  }
  else {
    generateln( "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\"");
    generateln( "    \"http://www.w3.org/TR/REC-html40/strict.dtd\">");
  }
  generateln( "<html>" ) ;
  generateln( "<head>" ) ;
  generateln( "<meta http-equiv=\"Content-Type\"" ) ;
  generateln( "content=\"text/html; charset=iso-8859-1\">" ) ;
  generate( "<meta name=\"GENERATOR\" content=\"" ) ;
  generate( PACKAGE " " VERSION ) ;
  generate( "\nby Lorenzo Bettini, lorenzo.bettini@penteres.it" ) ;
  generate( "\nhttp://w3.newnet.it/bettini" ) ;
  generate( "\nhttp://www.gnu.org/software/" PACKAGE "/" PACKAGE ".html" ) ;
  generateln( "\">" ) ;
  generate( "<title>" ) ;
  generate( ( docTitle ? docTitle : 
              ( inputFileName ? inputFileName : "source file" ) ) ) ;
  generateln( "</title>" ) ;
  if( cssUrl != 0 ) {
    generate( "<link rel=\"stylesheet\" href=\"" );
    generate( cssUrl );
    generateln( "\" type=\"text/css\">");
  }
  generateln( "</head>" ) ;
  if( cssUrl == 0 ) {
    generate( "<body bgcolor=\"#FFFFFF\" text=\"#000000\" link=\"#0000EE\" " ) ;
    generateln( "vlink=\"#551A8B\" alink=\"#FF0000\">" ) ;
  }
  else {
    generateln( "<body>" ) ;
  }
}

void print_bottom() {
  generateln( "</body>" ) ;
  generateln( "</html>" ) ;
}

void generate( const char *s ) {
  GlobalGenerator->generate(s) ;
}

void
generate( const char *s, int start, int end )
{
  GlobalGenerator->generate(s, start, end) ;
}

void generateln( const char *s ) {
  GlobalGenerator->generateln(s) ;
}

void generateNewLine() {
  generateln( "" ) ;
}

void generateTab() {
  if ( tabSpaces )
    for ( register int i = 0 ; i < tabSpaces ; ++i )
      generate( SPACE_CHAR ) ;
  else
    generate( "\t" ) ;
}

void startComment( const char *s )
{
  CommentGenerator->beginText(s) ;
}

void endComment( const char *s )
{
  CommentGenerator->endText(s) ;
}

void generateComment( const char *s ) {
  CommentGenerator->generateEntire(s) ;
}

void startString( const char *s )
{
  StringGenerator->beginText(s) ;
}

void endString( const char *s )
{
  StringGenerator->endText(s) ;
}

void generateString( const char *s ) {
  StringGenerator->generateEntire(s) ;
}

void generateKeyWord( const char *s ) {
  KeywordGenerator->generateEntire(s) ;
}

void generateBaseType( const char *s ) {
  TypeGenerator->generateEntire(s) ;
}

void generateNumber( const char *s ) {
  NumberGenerator->generateEntire(s) ;
}

void startTAG( const char *tag, const char *attr, const char *val ) {
  (*sout) << "<" << tag ;
  if ( attr && val )
    (*sout) << " " << attr << "=" << val ;
  (*sout) << ">" ;
}

void endTAG( const char *tag ) {
  (*sout) << "</" << tag << ">" ;
}

void startColor( const char *color ) {
  startTAG( FONT_TAG, COLOR_TAG, color ) ;
}

void endColor() {
  endTAG( FONT_TAG ) ;
}

void
print_version()
{
  cout << PACKAGE " " VERSION << endl ;

  print_text( copyright_text_length, copyright_text ) ;
}

void
print_help()
{
  print_text( helptext_text_length, helptext_text ) ;
}

void
print_text( int len, char *text[] )
{
  for ( int i = 1 ; i <= len ; ++i )
    cout << text[i] << endl ;
}