/** 
 *  Yudit Unicode Editor Source File
 *
 *  GNU Copyright (C) 1997-2023  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/STypes.h>
#include <stoolkit/SUtil.h>
#include <stoolkit/SStringVector.h>
#include <stoolkit/SIO.h>


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

#define BUFFER_SIZE 512

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

#define SS_UNIX 0
#define SS_DOS 1
#define SS_MAC 2
/**
 * This is a stoolkit encoder/decoder
 * @author: Gaspar Sinai <gaspar@yudit.org>
 * @version: 2000-04-23
 * This library is not multi-threaded. Therefor we need event handlers.
 */
int
main (int argc, char *argv[])
{
  const char* ifile="-";
  const char* ofile="-";
  FILE* output=stdout;
  FILE* input=stdin;
  const char* iencoding="utf-8";
  const char* oencoding="utf-8";
  int   fromd = SS_UNIX;
  int   tod = SS_UNIX;

  SUniMap::guessPath();
 
  int i;
  for (i=1; i<argc; i++)
  {
    if (strcmp ("-encode", argv[i])==0 && i<argc-1)
    { 
      oencoding =  argv[i+1]; i++;
    }
    else if (strcmp ("-fromdos", argv[i])==0)
    { 
      fromd = SS_DOS;
    }
    else if (strcmp ("-todos", argv[i])==0)
    { 
      tod = SS_DOS;
    }
    else if (strcmp ("-tomac", argv[i])==0)
    { 
      tod = SS_MAC;
    }
    else if (strcmp ("-frommac", argv[i])==0)
    { 
      fromd = SS_MAC;
    }
    else if (strcmp ("-decode", argv[i])==0 && i<argc-1)
    { 
      iencoding =  argv[i+1]; i++;
    }
    else if (strcmp ("-out", argv[i])==0 && i<argc-1)
    { 
      ofile =  argv[i+1]; i++;
#ifdef USE_WINAPI
      if ((output = fopen (ofile, "wb")) == 0)
#else
      if ((output = fopen (ofile, "w")) == 0)
#endif
      {
        fprintf (stderr, "uniconv: 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++;
#ifdef USE_WINAPI
      if ((input = fopen (ifile, "rb")) == 0)
#else
      if ((input = fopen (ifile, "r")) == 0)
#endif
      {
        fprintf (stderr, "uniconv: can not open '%s' to read.\n", ifile);
        return 1;
      }
    }
    else
    {
      usage();
      return 1;
    }
  }
  SEncoder ic(iencoding);
  if (!ic.isOK())
  {
    fprintf (stderr, "uniconv: can not find converter '%s'\n", iencoding);
    return 1;
  }
  SEncoder oc(oencoding);
  if (!oc.isOK())
  {
    fprintf (stderr, "uniconv: can not find converter '%s'\n", oencoding);
    return 1;
  }
  SStringVector lines;
  SString remaining;
  SStringVector delimiters = ic.delimiters();
  char* buff = new char[BUFFER_SIZE];
  CHECK_NEW (buff);
  int len; 
  SV_UCS4 dosrn;
  dosrn.append((SS_UCS4) '\r');
  dosrn.append((SS_UCS4) '\n');
  SV_UCS4 unixn;
  unixn.append((SS_UCS4) '\n');
  SV_UCS4 macr;
  macr.append((SS_UCS4) '\r');
  while (!feof(input) && (len=fread(buff, 1, BUFFER_SIZE, input))>0)
  {
    SString s(buff, len);
    remaining.append(s);
  }
  SV_UCS4 res = ic.decode (remaining, false);
  if (fromd == SS_DOS)
  {
    res.replaceAll (dosrn, unixn);
  }
  if (fromd == SS_MAC)
  {
    res.replaceAll(macr, unixn);
  }
  if (tod == SS_MAC)
  {
    res.replaceAll(unixn, macr);
  }
  if (tod == SS_DOS)
  {
    res.replaceAll (dosrn, unixn);
    res.replaceAll (unixn, dosrn);
  }
  SString w = oc.encode (res);
  int wlen = fwrite(w.array(), 1, w.size(), output);
  if (wlen!= (int) w.size())
  {
    fprintf (stderr, "uniconv: failed to write %s [%d/%d].\n", ofile, wlen, w.size());
    delete[] buff;
    return 1;
  }
  fclose (input);
  fclose (output);
  delete[] buff;
  return 0;
}

static void
usage ()
{
  SString pathStr;
  SStringVector l = SUniMap::getPath();
  
  pathStr = l.join (",");

  SStringVector enc = SEncoder::builtin();
  SString supStr = enc.join(", ");

  SStringVector extEnc = SEncoder::external();
  SString supExt = extEnc.join(", ");


  fprintf (stdout, version, SD_YUDIT_VERSION);
  fprintf (stdout,   "USAGE: uniconv [-out file] [-in file] [-decode name] [-encode name] [-fromdos] [-todos] [-frommac] [-tomac] \n\n");
  fprintf (stdout, "Currently known built-in encodings:   \n");
  fprintf (stdout, "%*.*s\n\n", SSARGS(supStr));
  fprintf (stdout, "Currently known external encodings:   \n");
  fprintf (stdout, "%*.*s\n\n", SSARGS(supExt));
  fprintf (stdout, "datapath settings:\n%*.*s\n\n", SSARGS(pathStr));
  fprintf (stdout, "example: /uniconv -decode Hungarian -encode iso-8859-2\n");
  fprintf (stdout, "example: Sinai Ga'spa'r <eof>\n");
}

