/** 
 *  Yudit Unicode Editor Source File
 *
 *  GNU Copyright (C) 1997-2006  Gaspar Sinai <gaspar@yudit.org>  
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License, version 2,
 *  dated June 1991. See file COPYYING for details.
 *
 *  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 <stoolkit/SUniMap.h>
#include <stoolkit/SEncoder.h>
#include <stoolkit/SExcept.h>
#include <stoolkit/SString.h>
#include <stoolkit/SStringVector.h>
#include <stoolkit/SIO.h>
#include <stoolkit/SIOStream.h>
#include <stoolkit/SEncoder.h>
#include <stoolkit/SUtil.h>
#include <stoolkit/STypes.h>
#include <swindow/SFont.h>
#include <swindow/SFontImpl.h>
#include <swindow/SScriptProcessor.h>
#include <swindow/SPrinter.h>
#include <swidget/SUniPrint.h>

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define BUFFER_SIZE 512

static const char *version="uniprint version %s GNU(c) Gaspar Sinai\n";
static void usage ();

#define SS_UNIX 0
#define SS_DOS 1
#define SS_MAC 2

#define DEFAULT_HEADER 10.0
#define DEFAULT_BODY 12.0

/**
 * This is a printing utility to simply and nicely print out
 * utf-8 text files.
 * FIXME:
 * ./uniprint -size 12 -font cyberbit.ttf -out aa ../doc/UTF-8-test.txt  
 * will produce bad things.
 * @author: Gaspar Sinai <gaspar@yudit.org>
 * @version: 2000-07-08
 */
int
main (int argc, char *argv[])
{
  const char* ifile = 0;
  const char* ofile = 0;
  const char* printer = 0;
  const char* command = "lpr";
  const char* iencoding ="utf-8";
  SStringVector font;
  bool shownl = false;
  bool isleft = false;
  bool isright = false;
  bool wrap = false;
  double headerSize = DEFAULT_HEADER;
  double bodySize = DEFAULT_BODY;
  
  SUniMap::guessPath();
  SFontImpl::guessPath();

  SPrinter::SMedia media = SPrinter::A4;
  SPrinter::SOrientation orient = SPrinter::PORTRAIT;

  int i;

  SInputStream is;
  SOutputStream os;

  for (i=1; i<argc; i++)
  {
    if (strcmp ("-decode", argv[i])==0 && i<argc-1)
    { 
      iencoding =  argv[i+1]; i++;
    }
    else if (strcmp ("-media", argv[i])==0 && i<argc-1)
    { 
      i++;
      if (strcmp ("A3", argv[i])==0) media = SPrinter::A3;
      else if (strcmp ("A4", argv[i])==0) media = SPrinter::A4;
      else if (strcmp ("A5", argv[i])==0) media = SPrinter::A5;
      else if (strcmp ("B4", argv[i])==0) media = SPrinter::B4;
      else if (strcmp ("B5", argv[i])==0) media = SPrinter::B5;
      else if (strcmp ("Executive", argv[i])==0) media = SPrinter::Executive;
      else if (strcmp ("Folio", argv[i])==0) media = SPrinter::Folio;
      else if (strcmp ("Ledger", argv[i])==0) media = SPrinter::Ledger;
      else if (strcmp ("Legal", argv[i])==0) media = SPrinter::Legal;
      else if (strcmp ("Letter", argv[i])==0) media = SPrinter::Letter;
      else if (strcmp ("Quarto", argv[i])==0) media = SPrinter::Quarto;
      else if (strcmp ("Statement", argv[i])==0) media = SPrinter::Statement;
      else if (strcmp ("Tabloid", argv[i])==0) media = SPrinter::Tabloid;
      else media = SPrinter::A4;
    }
    else if (strcmp ("-L", argv[i])==0)
    { 
      orient = SPrinter::LANDSCAPE;
    }
    else if (strcmp ("-landscape", argv[i])==0)
    { 
      orient = SPrinter::LANDSCAPE;
    }
    else if (strcmp ("-printer", argv[i])==0 && i<argc-1)
    { 
      printer =  argv[i+1]; i++;
    }
    else if (strcmp ("-font", argv[i])==0 && i<argc-1)
    { 
      font.append (argv[i+1]); i++;
    }
    else if (strcmp ("-break", argv[i])==0)
    { 
      shownl = true;
    }
    else if (strcmp ("-us", argv[i])==0)
    { 
      SScriptProcessor::support (true);
    }
    else if (strcmp ("-nus", argv[i])==0)
    { 
      SScriptProcessor::support (false);
    }
    else if (strcmp ("-left", argv[i])==0)
    { 
      isleft = true;
    }
    else if (strcmp ("-right", argv[i])==0)
    { 
      isright = true;
    }
    else if (strcmp ("-wrap", argv[i])==0)
    { 
      wrap = true;
    }
    else if (strcmp ("-hsize", argv[i])==0 && i<argc-1)
    { 
       i++;
       if (sscanf (argv[i], "%lf", &headerSize) == 0 
             || (headerSize <= 1.0&&headerSize!=0.0) || headerSize > 100.0)
       {
         fprintf (stderr, "header size out of range[1.0-100.0]: %s", argv[i]);
         return -1;
       }
       if (headerSize==0.0) headerSize = 1.0;
    }
    else if (strcmp ("-size", argv[i])==0 && i<argc-1)
    { 
       i++;
       if (sscanf (argv[i], "%lf", &bodySize) == 0 
             || bodySize < 1.0 || bodySize > 1000.0)
       {
         fprintf (stderr, "text size out of range[1.0-1000.0]: %s", argv[i]);
         return -1;
       }
    }
    else if (strcmp ("-out", argv[i])==0 && i<argc-1)
    { 
      ofile =  argv[i+1]; i++;
      if (ofile[0] == '-')
      {
        SPipe p;
        os = p.getOutputStream();
      }
      else
      {
        SFile f (ofile);
        os = f.getOutputStream();
      }
      if (!os.isOK())
      {
        fprintf (stderr, "uniprint: can not open '%s' to write.\n", ofile);
        return 1;
      }
    }
    else if (strcmp ("-in", argv[i])==0 && i<argc-1)
    { 
      ifile =  argv[i+1]; i++;
    }
    else if (argv[i][0] == '-')
    {
      usage();
      return 1;
    }
    else 
    {
      if (i+1==argc)
      {
        ifile = argv[i];
        //fprintf (stderr, "only 1 file will get printed: %s\n", ifile);
        break;
      }
      usage();
      return 1;
    }
  }

  /* Sub processing */

  /* STDIN */
  if (ifile == 0) ifile = "-";

  /* LPR */
  if (ofile == 0)
  {
    ofile = command;
    SString c (command);
    if (printer)
    {
      c.append (" -P ");
      c.append (printer);
    }
    fprintf (stderr, "opening command: %*.*s\n", SSARGS(c));
    SPipe p (c);
    os = p.getOutputStream();
    if (!os.isOK())
    {
      fprintf (stderr, "uniprint: can not open '%*.*s' to write.\n", SSARGS(c));
      return 1;
    }
  }
  
  SString ifileString;
  /* open input file */
  if (ifile[0] == '-')
  {
    SPipe p;
    is = p.getInputStream();
  }
  else
  {
    SFile f (ifile);
    is = f.getInputStream();
    ifileString = SString (ifile);
  }
  if (!is.isOK())
  {
     fprintf (stderr, "uniprint: can not open '%s' to read.\n", ifile);
     return 1;
  }

  SEncoder ic(iencoding);
  if (!ic.isOK())
  {
    fprintf (stderr, "uniprint: can not find converter '%s'\n", iencoding);
    return 1;
  }
  SReader reader(is);
  SWriter writer(os);
  SString s;
  reader.read (&s);

  SV_UCS4 res = ic.decode (s);
  SV_UCS4 header;

  SPrinter prnt(writer, (SPrinter::SType) 0, media,  orient);

  /**
   * FIXME: move this to yudit config.
   */
  if (font.size() ==0)
  {
    SProperties p;
    loadProperties(&p);
    if (p.get("yudit.font.TrueType"))
    {
      SStringVector vf (p["yudit.font.TrueType"]);
      fprintf (stderr, "No fonts were specified trying property `yudit.font.TrueType'.\n");
      for (unsigned int m=0; m<vf.size(); m++)
      {
        SStringVector nvf(vf[m], ":");
        font.append (nvf[0]);
        fprintf (stderr, "No fonts were specified - adding %*.*s\n", 
            SSARGS(nvf[0]));
      }
    }
    if (font.size() ==0)
    {
      fprintf (stderr, "No fonts were specified - adding cyberbit.ttf,yudit.ttf:cp-1250\n");
      font.append ("cyberbit.ttf");
      font.append ("yudit.ttf:cp-1250");
    }
  }
  SFontImplVector himpl;
  SFontImplVector dimpl;
  for (unsigned int h=0; h<font.size(); h++)
  {
    SFontImpl impl (font[h], font[h]);
    himpl.append (impl);
    dimpl.append (impl);
  }
  SFont::put ("Header", himpl);
  SFont::put ("Document", dimpl);

  SUniPrint uniPrint(prnt, "Header", headerSize, "Document", bodySize);

  SEncoder utf8;

  uniPrint.setLineEndMark(shownl);
  if (isright) uniPrint.setDocumentEmbedding (SS_EmbedRight);
  if (isleft) uniPrint.setDocumentEmbedding (SS_EmbedLeft);
  uniPrint.setLineEndMark(shownl);
  uniPrint.setWordWrap(wrap);

  if (!uniPrint.print (ifileString, utf8.encode (res)))
  {
    fprintf (stderr, "uniprint: can not print.\n");
    return 1;
  }
  int pagecount = uniPrint.getPageCount();
  if (pagecount > 1)
  {
    fprintf (stderr, "uniprint: printed %d pages.\n", pagecount);
  }
  else
  {
    fprintf (stderr, "uniprint: printed %d page.\n", pagecount);
  }
  return 0;
}

static void
usage ()
{
  fprintf (stdout, version, SD_YUDIT_VERSION);
  fprintf (stdout,   "usage: uniprint [-out file] [-printer name] [-in file] [-decode name] \n");
  fprintf (stdout,   "[-media A4] [-break] [-right|-left] [-hsize header-font-size] [-size font-size]\n");
  fprintf (stdout,   "[-L|-landscape] [-wrap] [-font truetype.ttf [-font otherfont.ttf [...]] \n\n");
  fprintf (stdout,   "uniprint [-us] using uniscribe-clone rendering (default).\n");
  fprintf (stdout,   "uniprint [-nus] not using uniscribe-clone rendering.\n");
  fprintf (stdout,   "uniconv -h will get list of supported encodings.   \n");
}

