/*-------------------------------------------------------------------------*/
/*  J3W ver 6.40  3D Animation Kit                                         */
/*  j3wunit.cpp   11/ 3/99                                                 */
/*  Copyright (C) 1996 -1999  Jun Mizutani <mizutani.jun@nifty.ne.jp>      */
/*                      All rights reserved.                               */
/*                                                                         */
/*   This file is part of the J3W 3D Animation Kit, and is covered under   */
/*  the terms of the GNU General Public License, version 2. This file has  */
/*  NO WARRANTY. See file COPYING for copyright details.                   */
/*                                                                         */
/*-------------------------------------------------------------------------*/

#include <iostream.h>
#include <X11/keysym.h>
#include <sys/types.h>
#include <sys/time.h>
#include <unistd.h>
#include <termios.h>
#ifdef AIX
#include <sys/select.h>
#endif
#include "version.h"
#include "screen.h"
#include "scrnx.h"
#include "xkey.h"
#include "spaceh3d.h"
#include "j3djob.h"

/*  500processes, 500objects, data memory for default process:100  */
const int FRONT_CLIP = 50;
const int BACK_CLIP  = 4000000;
const int MAX_OBJECT = 500;
const int MAX_PROCESS = 500;
const int MAX_COMMON = 15000;
const int DEF_DATAMEM = 100;

static TSpaceH3D space0(MAX_OBJECT, FRONT_CLIP, long(BACK_CLIP));
static TJob* Job;
static int bStart;
static ScrnX Scrn;

void cbreak()
{
    int fd=0;
    struct termios term;

    tcgetattr(fd, &term);
    term.c_lflag &= ~ICANON;
    term.c_lflag |= ISIG;
    term.c_cc[VMIN] = 1;
    term.c_cc[VTIME] = 0;
    tcsetattr(fd, TCSANOW, &term);
}

void echo()
{
    int fd=0;
    struct termios term;

    tcgetattr(fd, &term);
    term.c_lflag |= ECHO;
    tcsetattr(fd, TCSANOW, &term);
}

void nocbreak()
{
    int fd=0;
    struct termios term;

    tcgetattr(fd, &term);
    term.c_lflag |= ICANON;
    tcsetattr(fd, TCSANOW, &term);
}

void noecho()
{
    int fd=0;
    struct termios term;

    tcgetattr(fd, &term);
    term.c_lflag &= ~(ECHO|ECHONL);
    tcsetattr(fd, TCSANOW, &term);
}

void J3WCreate()
{
    long DummyReg[16];
    Display* d;

    space0.set_screen(&Scrn);
    Job = new TJob(MAX_COMMON, MAX_PROCESS, &space0, (TScreen *)&Scrn);
    for(int i = 0; i<16; i++) DummyReg[i] = 0;
    Job->new_process(DEF_DATAMEM, 0, -1, DummyReg);
    cout << VersionStr << '\n';
    bStart = 0;
    d = Scrn.GetDisplay();

    noecho();
    cbreak();
}

void J3WOpen(short full, short sm, short dith, short zb)
{
    bStart = 0;
}

void J3WClose()
{
    if(Job != NULL) {
        delete Job;
        Job = NULL;
    }
    echo();
    nocbreak();
}

short J3WLoop()
{
    Display* d;
    XEvent event;
    KeySym sym;
    char string[10];
    fd_set  rfds;
    struct  timeval timeout;
    char    ch;
    int     ret;

    if(Job == NULL) return 1;

    FD_ZERO(&rfds);
    FD_SET(0, &rfds);
    timeout.tv_sec = 0;
    timeout.tv_usec = 0;
    ret = select(1, &rfds, (fd_set*)NULL, (fd_set*)NULL, &timeout);
    if (ret) {
        ret = read(0, &ch, 1);
        Job->SetKey(ch);
    }

    if(bStart)
      if( Job->job_scheduler() == 0 ) {
          bStart = 0;
          Job->ResetGraph();
          cout << '\n' << " [finished] \n";
          Scrn.restore_mode();
          return 1;
      } else {

          d = Scrn.GetDisplay();
          if (d != 0) {
            int pending = XPending(d);
            while (pending > 0) {
              XNextEvent(d, &event);
              switch(event.type) {
                case KeyPress :
                    if (XLookupString(&event.xkey, string, 10, &sym, NULL) == 1);
                        Job->SetKey(X2WKey(sym));
                    break;
              }
              pending--;
            }
          }
          return 0;
      }
    else return 0;
}

void J3WStart()
{
    if(bStart) bStart = 0;
    else {
       Job->StartTimer();
        bStart = True;
    }
}

short J3WNew(char *FileName)
{
    long DummyReg[16];

    space0.reset_space();
    if(Job != NULL) delete Job;

    Job = new TJob(15000, 500, &space0, (TScreen *)&Scrn);
    for(int i = 0; i<16; i++) DummyReg[i] = 0;
    Job->new_process(100,0,-1,DummyReg);
    bStart = 0;
    if(Job->LoadObjFile(FileName)) return 0;
    else return 1;
}

void J3WTextShow()
{
}

void J3WTextHide()
{
}

void J3WMidiOpen()
{
#ifdef MIDI_SUPPORT
    Job->MidiOpen();
#endif
}

void  J3WSetMem(short adr, long n)
{
    if((adr >= 0) && (adr < MAXCOMMON)) Job->SetCommonMem(adr, n);
}

long  J3WGetMem(short adr)
{
    if((adr >= 0) && (adr < MAXCOMMON))
        return Job->GetCommonMem(adr);
    else return 0;
}

short J3WDeviceCount(short typ)
{
    return 1;
}

char *J3WDeviceName(short typ, short no)
{
    return (char *)0;
}

void J3WSetDevice(short typ, short no)
{
}
