/*
 *  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 <pspwlan.h>
#include <pspkernel.h>
#include <psppower.h>
#include <pspctrl.h>

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

#include <SDL.h>

#include "psp_global.h"
#include "psp_sdl.h"
#include "psp_menu.h"
#include "psp_danzeff.h"
#include "psp_fmgr.h"
#include "psp_ssh.h"

# define PSPSSH_MAX_INPUT_LENGTH   1024

static int          loc_ssh_thid = -1;

static volatile int  loc_ssh_input_begin = 0;
static volatile int  loc_ssh_input_end   = 0;
static volatile char loc_ssh_input[PSPSSH_MAX_INPUT_LENGTH];

int
psp_ssh_is_data_to_ssh()
{
  return loc_ssh_input_begin != loc_ssh_input_end;
}

int
psp_ssh_get_data_to_ssh(char *buffer, int length)
{
  int src_index = loc_ssh_input_begin;
  int dst_index = 0;
  while (src_index != loc_ssh_input_end) {

    buffer[dst_index++] = loc_ssh_input[src_index];
    src_index = (src_index + 1) % PSPSSH_MAX_INPUT_LENGTH;

    if (dst_index >= length) break;
  }
  loc_ssh_input_begin = src_index;
}

int
psp_ssh_put_key_to_ssh(char key)
{
  loc_ssh_input[loc_ssh_input_end] = key;
  loc_ssh_input_end = (loc_ssh_input_end + 1) % PSPSSH_MAX_INPUT_LENGTH;
}

int
psp_ssh_put_data_to_ssh(char *data, int length)
{
  int index;
  for (index = 0; index < length; index++) {
    loc_ssh_input[loc_ssh_input_end] = data[index];
    loc_ssh_input_end = (loc_ssh_input_end + 1) % PSPSSH_MAX_INPUT_LENGTH;
  }
}

void
psp_ssh_send_to_console(char *buffer, int length)
{
  if (! length) return;

  psp_vt100_process(buffer, length);
}

void
psp_ssh_display_screen()
{
  psp_sdl_blit_console();
  psp_display_screen_menu_battery();
  psp_vt100_display_screen();
}

void
psp_ssh_thread(SceSize argc, void *argv)
{
  cli_main_run_session();
}

void
psp_ssh_clear_screen()
{
  psp_ssh_display_screen();
}

void
psp_ssh_start_main_thread()
{
  /* Launch ssh client thread */
  loc_ssh_thid = sceKernelCreateThread( "ssh_thread", 
     (SceKernelThreadEntry)psp_ssh_thread, 0x18, 0x10000, 0, 0 );

  if(loc_ssh_thid >= 0) {
    sceKernelStartThread(loc_ssh_thid, 0, 0);
  }
}


void
psp_ssh_main()
{
  SceCtrlData c;

  long new_pad;
  long old_pad;

  int  danzeff_mode = 0;
  int  danzeff_key;

  int last_time  = 0;

  while (1)  {

    psp_ssh_display_screen();

    if (danzeff_mode) {
      danzeff_moveTo(-50, -50);
      danzeff_render();
    }
    psp_sdl_flip();

    if (PSPSSH.psp_screenshot_mode) {
      PSPSSH.psp_screenshot_mode--;
      if (PSPSSH.psp_screenshot_mode <= 0) {
        psp_sdl_save_screenshot();
        PSPSSH.psp_screenshot_mode = 0;
      }
    }
   	sceKernelDelayThread(1000);

    sceCtrlReadBufferPositive(&c, 1);
    c.Buttons &= PSP_ALL_BUTTON_MASK;

    new_pad = c.Buttons;

    if ((old_pad != new_pad) || ((c.TimeStamp - last_time) > PSP_MENU_MIN_TIME)) {
      last_time = c.TimeStamp;
      old_pad = new_pad;

    } else continue;

    if (danzeff_mode) {

      danzeff_key = danzeff_readInput(c);

      if (danzeff_key < 0) {
        /* Control keys */
        psp_ssh_put_key_to_ssh(-danzeff_key);
      } else
      if (danzeff_key > DANZEFF_START) {
        if (danzeff_key >= ' ') {
          psp_ssh_put_key_to_ssh(danzeff_key);
        } else
        if (danzeff_key == DANZEFF_PAGE_UP) {
          psp_ssh_put_data_to_ssh("\033[5~", 4);
        } else 
        if (danzeff_key == DANZEFF_PAGE_DOWN) {
          psp_ssh_put_data_to_ssh("\033[6~", 4);
        } else 
        if (danzeff_key == DANZEFF_END) {
          psp_ssh_put_data_to_ssh("\033[F", 3);
        } else 
        if (danzeff_key == DANZEFF_HOME) {
          psp_ssh_put_data_to_ssh("\033[H", 3);
        } else 
        if (danzeff_key == DANZEFF_LEFT) {
          psp_ssh_put_data_to_ssh("\033[D", 3);
        } else 
        if (danzeff_key == DANZEFF_UP) {
          psp_ssh_put_data_to_ssh("\033[A", 3);
        } else 
        if (danzeff_key == DANZEFF_RIGHT) {
          psp_ssh_put_data_to_ssh("\033[C", 3);
        } else 
        if (danzeff_key == DANZEFF_DOWN) {
          psp_ssh_put_data_to_ssh("\033[B", 3);
        } else 
        if (danzeff_key == DANZEFF_INSERT) {
          psp_ssh_put_data_to_ssh("\033[2~", 4);
        } else 
# if 0
        if (danzeff_key == DANZEFF_DEL) {
          psp_ssh_put_data_to_ssh("\033[3~", 4);
        } else 
# else
        if (danzeff_key == DANZEFF_DEL) {
          psp_ssh_put_data_to_ssh("\b", 1);
        } else 
# endif
        if (danzeff_key == DANZEFF_ESCAPE) {
          psp_ssh_put_key_to_ssh('\033');
        } else 
        if (danzeff_key == DANZEFF_TAB) {
          psp_ssh_put_key_to_ssh('\t');
        } else
        if (danzeff_key == DANZEFF_F1) {
          psp_ssh_put_data_to_ssh("\033OP", 3);
        } else
        if (danzeff_key == DANZEFF_F2) {
          psp_ssh_put_data_to_ssh("\033OQ", 3);
        } else
        if (danzeff_key == DANZEFF_F3) {
          psp_ssh_put_data_to_ssh("\033OR", 3);
        } else
        if (danzeff_key == DANZEFF_F4) {
          psp_ssh_put_data_to_ssh("\033OS", 3);
        } else
        if (danzeff_key == DANZEFF_F5) {
          psp_ssh_put_data_to_ssh("\033[15~", 5);
        } else
        if (danzeff_key == DANZEFF_F6) {
          psp_ssh_put_data_to_ssh("\033[17~", 5);
        } else
        if (danzeff_key == DANZEFF_F7) {
          psp_ssh_put_data_to_ssh("\033[18~", 5);
        } else
        if (danzeff_key == DANZEFF_F8) {
          psp_ssh_put_data_to_ssh("\033[19~", 5);
        } else
        if (danzeff_key == DANZEFF_F9) {
          psp_ssh_put_data_to_ssh("\033[20~", 5);
        }

      } else 
      if ((danzeff_key == DANZEFF_START ) || 
          (danzeff_key == DANZEFF_SELECT)) 
      {
        danzeff_mode = 0;
        old_pad = new_pad = 0;

        psp_kbd_wait_no_button();
      }

      continue;
    }

    if ((c.Buttons & (PSP_CTRL_LTRIGGER|PSP_CTRL_RTRIGGER|PSP_CTRL_START)) ==
        (PSP_CTRL_LTRIGGER|PSP_CTRL_RTRIGGER|PSP_CTRL_START)) {
      /* Exit ! */
      psp_sdl_exit(0);
    } else
    if(new_pad & PSP_CTRL_SELECT) {
      /* Back to Main Menu */
      psp_ssh_menu();

    } else
    if(new_pad & PSP_CTRL_START) {
      danzeff_mode = 1;
    } else
    if(new_pad & PSP_CTRL_CROSS) {
      psp_ssh_put_key_to_ssh('\n');
    } else
    if(new_pad & PSP_CTRL_TRIANGLE) {
      psp_ssh_put_key_to_ssh('\t');
    } else
    if(new_pad & PSP_CTRL_SQUARE) {
      psp_ssh_put_key_to_ssh('\b');
    } else
    if(new_pad & PSP_CTRL_CIRCLE) {
      psp_ssh_put_key_to_ssh(' ');
    } else
    if(new_pad & PSP_CTRL_LTRIGGER) {
      psp_vt100_screen_scroll_down();
    } else
    if(new_pad & PSP_CTRL_RTRIGGER) {
      psp_vt100_screen_scroll_up();
    } else
    if (new_pad & PSP_CTRL_LEFT) {
      psp_ssh_put_data_to_ssh("\033[D", 3);
    } else 
    if (new_pad & PSP_CTRL_UP) {
      psp_ssh_put_data_to_ssh("\033[A", 3);
    } else 
    if (new_pad & PSP_CTRL_RIGHT) {
      psp_ssh_put_data_to_ssh("\033[C", 3);
    } else 
    if (new_pad & PSP_CTRL_DOWN) {
      psp_ssh_put_data_to_ssh("\033[B", 3);
    }
  }

  if (loc_ssh_thid != -1) {
    sceKernelExitDeleteThread(loc_ssh_thid);
    sceKernelWaitThreadEnd(loc_ssh_thid, NULL);
    loc_ssh_thid = -1;
  }
}
