/** 
 *  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.
 */

#ifdef USE_GETTEXT
extern "C"
{
#include <libintl.h>
}
#endif
#include <stdlib.h>

#include "gui/Main.h"
#include "gui/SYudit.h"

#include "stoolkit/SString.h"
#include "stoolkit/SStringVector.h"
#include "stoolkit/SProperties.h"
#include "stoolkit/SIO.h"
#include "stoolkit/SIOStream.h"
#include "stoolkit/SUniMap.h"
#include "stoolkit/SUtil.h"
#include "stoolkit/sedy/SSedy.h"
#include "swindow/SFontImpl.h"
#include "stoolkit/syntax/SSyntax.h"

#include "swindow/SAwt.h"
#include "swidget/SPanel.h"
#include "swidget/SFileDialog.h"
#include "swidget/SFileDialog.h"


#ifndef USE_WINAPI
#include <unistd.h> 
#include <pwd.h>
#include <sys/types.h>
#endif

static SString sedyInit();


#define TEST 0

#define DIALOG_TEST 1
#if TEST

#if DIALOG_TEST

#include <swidget/SFileDialog.h>
#include <swidget/STextDialog.h>

int
main (int argc, char* argv[])
{
    SAwt awt;
#if 1
    STextDialog * dialog = new STextDialog();
    dialog->setBackground(SColor("#7f7f7f"));
    dialog->getInput ("Title", "This is an even longer\nessage", 
        SDialog::SS_QUESTION);
#endif
#if 0 
    SFileDialog * dialog = new SFileDialog();
    dialog->setBackground(SColor("#7f7f7f"));
    dialog->getInput ("Open", false, false);
#endif
/*
    panel->resize (SDimension(520,300));
    panel->show();
    SEventHandler::start();
*/
    return (0);
}

#else /* DIALOG_TEST */

#include <swidget/SPanel.h>
#include <swidget/SIconFactory.h>
#include <swindow/SImage.h>
#include <stoolkit/SUniqueID.h>

class MyPanel : public SPanel 
{
public:
    MyPanel () {};
    virtual ~MyPanel() {};

 void redraw(SCanvas* w, int x, int y,
     unsigned int width ,unsigned int height)
{
    SStringVector list = SIconFactory::getIconList();
#if 0
    SIcon* icon = SIconFactory::getIcon(SString("EmbedLeft"));        
    SImage image = icon->getImage();        
    SVGBase* svgBase = image.getSVGBase();
    svgBase->setCanvas (window, SColor("white"));
    svgBase->render(25, 25, 1.0);
    svgBase->render(85, 25, 2.0);
    svgBase->render(190, 25, 4.0);
#else
//SUniqueID id;
//fprintf (stderr, "Id [%*.*s]\n", SSARGS(id));
    for (unsigned int i=0; i<list.size(); i++) {
        SIcon* icon = SIconFactory::getIcon(list[i]);        
        SImage image = icon->getImage();        
        unsigned int x = 10 + (i%10) * 50;
        unsigned int y = 10 + (i/10) * 50;
        window->putImage (x, y, image);
        SVGBase* svgBase = image.getSVGBase();
        if (svgBase) {
            svgBase->setCanvas (window, SColor("#7f7f7f"));
            svgBase->render(x + 25, y);
        }
    }
#endif
}

 void redraw2(SCanvas* w, int x, int y,
     unsigned int width ,unsigned int height)

{
    if (!window->beginImage (0, 0, "Image0", SColor("white"))) {
        fprintf (stderr, "Image"); 
        window->newpath (); 
        window->moveto (200,100); 
        window->lineto (100,200); 
        window->lineto (300,200); 
        window->closepath (); 
        SPen pen(SColor("yellow"), SColor("white"));
        window->fill (pen);
        pen.setLineWidth (1.0);
        pen.setForeground (SColor("black"));
        window->stroke (pen);
        
    }
    window->endImage();
}
};


int
main (int argc, char* argv[])
{
    SAwt awt;
    MyPanel * panel = new MyPanel();
    panel->setBackground(SColor("#7f7f7f"));
    panel->resize (SDimension(520,300));
    panel->show();
    SEventHandler::start();
    return (0);
}
#endif
#else

int
main (int argc, char* argv[])
{
  /* have to set the path before awt */
  SUniMap::guessPath ();
  SSyntax::guessPath ();

  unsigned int i; unsigned int j;
  SString home = getHome();
  SString yuditdir = getPrefix();
  
  SString dotdir = home;
  dotdir.append ("/");
  dotdir.append (".yudit");
  SDir d (dotdir);
  if (!d.exists())
  {
    if (d.create())
    {
      fprintf (stderr, "yudit: created directory `%*.*s'\n",
         SSARGS (dotdir));
    }
    else
    {
      fprintf (stderr, "yudit: can not create directory `%*.*s'\n",
         SSARGS (dotdir));
      // don't exit on windows ! They won't know a thing.
      //exit (1);
    }
  }
  else if (!d.readable())
  {
    fprintf (stderr, "yudit: Can not read directory `%*.*s'\n",
        SSARGS (dotdir));
  }

  SString fontdir(dotdir);
  fontdir.append ("/");
  fontdir.append ("fonts");
  SDir dfont (fontdir);
  if (!dfont.exists())
  {
    dfont.create ();
  }
  SString dotdata(dotdir);
  dotdata.append ("/");
  dotdata.append ("data");
  SDir ddotdata (dotdata);
  if (!ddotdata.exists())
  {
    ddotdata.create ();
  }
  SString dotsyntax(dotdir);
  dotsyntax.append ("/");
  dotsyntax.append ("syntax");
  SDir ddotsyntax (dotsyntax);
  if (!ddotsyntax.exists())
  {
    ddotsyntax.create ();
  }

  SStringVector args;
  SProperties   properties;

  

  /**
   *-----------------------------------------------------------------------
   * The default configuration section this will always be here.
   *-----------------------------------------------------------------------
   */
  //properties.put ("yudit.datapath", );
  //properties.put ("yudit.fontpath", );
  properties.put ("yudit.scale", "1.0");
  properties.put ("yudit.background", "gray50");
  properties.put ("yudit.label.foreground", "moccasin");
  properties.put ("yudit.title.foreground", "white");


  properties.put ("yudit.default.font", "default");
  properties.put ("yudit.default.fontsize", "16");
  properties.put ("yudit.default.geometry", "765x510");
  properties.put ("yudit.freehand.converter", "kanji");

  properties.put ("yudit.editor.background", "black");
  properties.put ("yudit.editor.left.foreground", "green");
  properties.put ("yudit.editor.right.foreground", "yellow");

  properties.put ("yudit.editor.caret.left.foreground", "red");
  properties.put ("yudit.editor.caret.right.foreground", "red");
  properties.put ("yudit.editor.showbreak", "true");

  /* enable syntax simple for people with old config file */
  properties.put ("yudit.editor.syntax", "simple");

  /* don't enable wordwrap for people with old config file */
  properties.put ("yudit.editor.wordwrap", "false");

  /* do over-the spot xim */
  properties.put ("yudit.editor.xinputs.style", "preedit-over-status-under");

  properties.put ("yudit.command.background", "black");
  properties.put ("yudit.command.left.foreground", "green");
  properties.put ("yudit.command.right.foreground", "yellow");
  properties.put ("yudit.command.caret.left.foreground", "red");
  properties.put ("yudit.command.caret.right.foreground", "red");
  properties.put ("yudit.slider.background", "#497986");
  properties.put ("yudit.editor.fontsizes", "10,12,14,16,24,48");
  properties.put ("yudit.editor.fonts", "default,TrueType,Bitmap");
#ifdef USE_WINAPI
  properties.put ("yudit.editor.inputs", 
    "straight,unicode,WindowsIM,Hungarian,Hangul,"
    "Kana,Mnemonic,Esperanto,Arabic,Hebrew,"
    "Russian,OldHungarian");
#else
  properties.put ("yudit.editor.inputs", 
    "straight,unicode,kinput2,Hungarian,Hangul,"
    "Kana,Mnemonic,Esperanto,Arabic,Hebrew,"
    "Russian,OldHungarian");
#endif
  if (isWinAPI())
  {
    properties.put ("yudit.editor.xinputs", "");
  }
  else
  {
    properties.put ("yudit.editor.xinputs", "utf-8:en_GB,utf-8:hu_HU,kinput2:ja_JP.eucJP,xcin:zh_TW.big5,Ami:ko_KR,xcin-zh_CN.GB2312:zh_CN.GB2312");
  }
  properties.put ("yudit.editor.fontsize", "16");
  properties.put ("yudit.editor.font", "default");
  properties.put ("yudit.editor.input", "straight");
  properties.put ("yudit.fonts", "default,TrueType,Bitmap");
  properties.put ("yudit.font.TrueType", 
       "arial.ttf,msgothic.ttf,gulim.ttf,"
       "-*-*-*-*-*--*-*-*-*-*-*-iso8859-1,"
       "cyberbit.ttf,yudit.ttf:cp-1250");

  properties.put ("yudit.font.Bitmap", 
   "-gnu-unifont-medium-r-normal--16-160-75-75-c-80-iso10646-1,*-iso8859-1,"
   "jisx0208.1983-0,"
   "jisx0201.1976-0,"
   "-sony-fixed-medium-r-normal--*-230-75-75-c-120-iso8859-1");

  properties.put ("yudit.default.printer.options", "");
  properties.put ("yudit.default.preview.command", "gv");

  /**
   * override everything with system prop 
   */
  SString yuditconfig(yuditdir);
  yuditconfig.append ("/config/yudit.properties");
  if (!loadProperties (yuditconfig, &properties))
  {
    fprintf (stderr, "could not load `%*.*s'.\n", SSARGS(yuditconfig));
  }
  else
  {
    //fprintf (stderr, "loaded `%*.*s'.\n", SSARGS(yuditconfig));
  }

  /**
   * User defined properties 
   */
  SProperties userProperties;
  userProperties.put ("yudit.default.clipboard.encoding", "iso-2022-x11");
  userProperties.put ("yudit.default.filetype", "utf-8");

  SString userconfig (dotdir);
  userconfig.append ("/yudit.properties");
  bool firsttime = false;
  if (!loadProperties (userconfig, &userProperties))
  {
    firsttime = true;
    //fprintf (stderr, "could not load `%*.*s'(not an error).\n", 
    //       SSARGS(userconfig));
  }
  else
  {
    //fprintf (stderr, "loaded `%*.*s'.\n", SSARGS(userconfig));
    const SString *str = userProperties.get ("yudit.default.preview.command");
    /* compatibility. remove this. */
    if (str!=0)
    { 
      const SString& ustr = *str;
      if (ustr.size() > 0 && ustr[0] == '-' && ustr[1] == 'e')
      {
         const SString& gvle = properties["yudit.default.preview.command"];
         fprintf (stderr, "moving yudit.default.preview.command '%*.*s' to '%*.*s' (compatibility 2.5).\n", 
           SSARGS(ustr), SSARGS(gvle));
         fprintf (stderr, "To get rid of this message set your yudit.default.preview.command in %*.*s (like: gv).\n", 
           SSARGS (userconfig));
         userProperties.put ("yudit.default.preview.command", SString(gvle));
      }
    }
  }
  
  SProperties allProperties(properties);
  userProperties.remove ("00HEADER.#");
  userProperties.remove ("yudit.default.language.#");

  // rewrite old user properties
  if (userProperties.get ("00HEADER.version.yudit") == 0 
     || userProperties["00HEADER.version.yudit"].compare (SD_YUDIT_VERSION) < 0)
  {
    // upgrade: our preferred geometry has changed.
    userProperties.put ("yudit.default.geometry", "765x510");
  }
  allProperties.merge (userProperties);
  if (allProperties.get ("yudit.default.file")==0)
  {
    allProperties.put ("yudit.default.file", "untitled.utf8");
  }

  /* you can not override this */
  allProperties.put ("yudit.config", userconfig);
  SStringVector ve(allProperties["yudit.editor.fonts"]);
  SStringVector vy(allProperties["yudit.fonts"]);

  for (i=0; i<ve.size(); i++)
  {
    for (j=0; j<vy.size(); j++)
    {
       if (vy[j] == ve[i]) break;
    }
    if (j == vy.size()) vy.append (ve[i]);
  }

  /**
   * Check if all fonts are defined.
   */
  SProperties fontProps;
  for (i=0; i<vy.size(); )
  {
    if (vy[i] == "default")
    {
      i++;
      continue;
    }
    SString str("yudit.font.");
    str.append (vy[i]);
    if (!allProperties.get (str))

    {
      fprintf (stderr, "removing: '%*.*s' from list - not defined.\n", SSARGS(str));
      //fprintf (stderr, "ALL=\n%*.*s\n", SSARGS(allProperties.toString()));
      vy.remove(i);
      i=0;
    }
    else
    {
      fontProps.put (vy[i], allProperties[str]);
      i++;
    }
  }

  SAwt awt;
  if (!awt.implemented())
  {
    if (!awt.hasGUI()) 
    {
      fprintf (stderr, "AWT is not implemented on this platform.\n");
      fprintf (stderr, "This can happen if X11 Development libraries\n"); 
      fprintf (stderr, "were missing when configure was executed.\n"); 
      fprintf (stderr, "Other Yudit programs (uniconv, uniprint) should work.\n"); 
      return 2;
    }
    else
    {
      fprintf (stderr, "Try to set your DISPLAY environment variable.\n");
      return 1;
    }
  }

  /* have to set the path after first awt */
  SFontImpl::guessPath ();
  SString clipEnc = allProperties["yudit.default.clipboard.encoding"];
  if (clipEnc.size())
  {
    awt.setEncoding (clipEnc);
//SStringVector all = SUniMap::getPath();
//SString s = all.join (",");
//fprintf (stderr, "setting clipboard encoder to %*.*s\n", SSARGS(clipEnc));
  }

  /* init fonts */
  for (i=0; i< vy.size(); i++)
  {
    SString key = vy[i];
    if (key == "default") continue;
    SString str = fontProps[key];
    SStringVector curr(str);
    
    SFontImplVector list;
    for (j=0; j<curr.size(); j++)
    {
      /* encoding is optional */
      SStringVector v(curr[j], ":");
      SString enc = v[0];
      if (v.size()>1 && v[1].size()!=0) enc = v[1];
      SFontImpl impl (v[0], enc);

      if (v.size()>2 && v[2].size()>0)
      {
         SStringVector pvect(v[2], ";");
         SProperties props;
         for (unsigned int j=0; j<pvect.size(); j++)
         {
            SStringVector vv(pvect[j], "=", true);
            if (vv.size() > 1)
            {
               props.put (vv[0], vv[1]);
            }
            else
            {
               props.put (vv[0], "true");
            }
         }
         impl.setAttributes(props);
      }
      list.append (impl);
    }
    //fprintf (stderr, "initializing %*.*s\n", SSARGS(key));
    SFont::put (key, list);
  }

  int k; 
  for (k=0; k<argc; k++)
  {
    args.append (argv[k]);
  }
  if (argc==1 && firsttime)
  {
    args.append ("-help");
  }
  SString ldir (yuditdir);
  ldir.append ("/locale");
  initTranslate ("messages", ldir);
  if (allProperties.get ("yudit.default.language"))
  {
    SString lang = allProperties["yudit.default.language"];
    lang.replaceAll(" ", "");
    if (lang.size()>0 && lang!=SString("default"))
    {
       /* no spaces */
       setLanguage (lang);
    }
    else if (lang==SString("default"))
    {
      setLanguage (getSystemLanguage ("en"));
    }
  }

  SString sedyLib = sedyInit ();
  SString scaleStr = allProperties["yudit.scale"];
  scaleStr.append ((char)0);
  float scale = 1.0;
  char buff[8];
  if (sscanf (scaleStr.array(), "%f%1s", &scale, buff) != 1) 
  {
    fprintf (stderr, "Yudit: decimal number expected for [yudit.scale=%s]\n", 
        scaleStr.array());
    scale = 1.0;
  }
  if (scale > SB_YUDIT_MAX_SCALE) {
    fprintf (stderr, "Yudit: [yudit.scale=%s] not in range [1.0-%.1f]\n", scaleStr.array(), SB_YUDIT_MAX_SCALE);
    scale = 3.0;
  }
  if (scale < 1.0) {
    fprintf (stderr, "Yudit: [yudit.scale=%s] not in range [1.0-%.1f]\n", scaleStr.array(), SB_YUDIT_MAX_SCALE);
    scale = 1.0;
  }
  SAwt::setScale (scale);

  SYudit *yudit = new SYudit (args, allProperties, sedyLib);
  yudit->show();
  yudit->center();
  SEventHandler::start();
  return 0;
}

static SString sedyInit () {
  SString c1 = getHome();
  c1.append ("/.yudit/syntax");
  SString c2 = getPrefix();
  c2.append ("/syntax");
  SStringVector v;
  v.append (c1);
  v.append (c2);
  SString lib = SSedy::loadLibrary (v);
  if (lib.size() != 0) {
     // fprintf (stderr, "Sedy: %*.*s\n", SSARGS(lib));
    SString test = "Test String...";
    SString pass = "VeryGoodPassword";
    SSedy sedy;
    SString enc = sedy.encrypt (test, pass);
    SString dec = sedy.decrypt (enc, pass);
    if (dec != test) {
        fprintf (stderr, "Sedy: %*.*s failed test.\n", SSARGS(lib));
    }
    //return SString("");
  }
  //SSedy sedy;
  //fprintf (stderr, "Sedy: %*.*s\n", SSARGS(sedy.getLastError()));
  return SString(lib);
}

#endif
