/*
 * tngp/chooser.c
 *
 * Copyright (C) 2022 bzt
 *
 * 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 3 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.
 *
 * @brief Route chooser popup
 *
 */

#include "tngp.h"

int chooser_idx = -1, *chooser_flag = NULL, *chooser_regs = NULL, chooser_o = 0, chooser_p = 0;
static SDL_Rect chooser_dst[13];

/**
 * Initialize chooser
 */
void chooser_init(int idx, int *flag, int *regs)
{
    int i;
    if(idx >= 0 && idx < world.numchr && regs) {
        chooser_idx = idx;
        if(flag) { chooser_flag = flag; *flag = 1; }
        chooser_regs = regs;
        /* clear regs a, b, c */
        chooser_regs[0] = chooser_regs[1] = chooser_regs[2] = 0;
        for(i = 0; i < world.choosers[idx].numopts; i++)
            memset(&world.choosers[idx].opts[i].dst, 0, sizeof(world.choosers[0].opts[0].dst));
        chooser_o = chooser_p = 0;
    }
}

/**
 * Free resources
 */
void chooser_free()
{
    chooser_idx = -1;
    if(chooser_flag) { *chooser_flag = 0; chooser_flag = NULL; }
    chooser_regs = NULL;
}

/**
 * Controller
 */
int chooser_ctrl()
{
    world_chropt_t *list;
    int i;

    if(chooser_idx < 0 || chooser_idx >= world.numchr || !chooser_regs || !world.choosers || !world.choosers[chooser_idx].opts ||
      !world.players)
        return 0;
    list = world.choosers[chooser_idx].opts;
    switch(event.type) {
        case SDL_KEYDOWN:
            ui_input_gp &= ~1;
            switch(event.key.keysym.sym) {
                case SDLK_AC_BACK:
                case SDLK_F10:
                case SDLK_BACKSPACE:
                case SDLK_ESCAPE:
/* deliberately no escape, player must choose a valid option
                    chooser_regs[0] = 0;
                    if(!list[chooser_o].keep) chooser_free();
*/
                break;
                case SDLK_SPACE:
                case SDLK_RCTRL:
                case SDLK_RETURN: chooser_p = 1; break;
                case SDLK_UP:
                case SDLK_LEFT:
left:               if(chooser_o < 0) chooser_o = world.choosers[chooser_idx].numopts;
                    do {
                        if(chooser_o) chooser_o--; else chooser_o = world.choosers[chooser_idx].numopts - 1;
                    } while(list[chooser_o].dst.w < 1);
                break;
                case SDLK_TAB:
                case SDLK_DOWN:
                case SDLK_RIGHT:
right:              do {
                        if(chooser_o < world.choosers[chooser_idx].numopts - 1) chooser_o++; else chooser_o = 0;
                    } while(list[chooser_o].dst.w < 1);
                break;
            }
        break;
        case SDL_KEYUP:
            chooser_p = 0;
            switch(event.key.keysym.sym) {
                case SDLK_SPACE:
                case SDLK_RCTRL:
                case SDLK_RETURN:
dosel:              if(chooser_o >= 0 && chooser_o < world.choosers[chooser_idx].numopts && list[chooser_o].dst.w > 0) {
                        /* set the described attribute or reg */
                        if(list[chooser_o].prov.type < 2)
                            script_setattr(&world.players[0].data, list[chooser_o].prov.attr, list[chooser_o].prov.value);
                        else
                            chooser_regs[list[chooser_o].prov.type - 2] = list[chooser_o].prov.value;
                        /* and set the selected option + 1 into reg a */
                        chooser_regs[0] = chooser_o + 1;
                        if(!list[chooser_o].keep) chooser_free();
                    }
                break;
            }
        break;
        case SDL_MOUSEBUTTONDOWN: ui_input_gp &= ~1; chooser_p = 1; break;
        case SDL_MOUSEBUTTONUP: chooser_p = 0; goto dosel; break;
        case SDL_MOUSEMOTION:
            ui_input_gp &= ~1; chooser_o = -1;
            for(i = 0; i < world.choosers[chooser_idx].numopts; i++)
                if(list[i].dst.w > 0 && event.motion.x >= list[i].dst.x && event.motion.x < list[i].dst.x + list[i].dst.w &&
                  list[i].dst.h > 0 && event.motion.y >= list[i].dst.y && event.motion.y < list[i].dst.y + list[i].dst.h) {
                    chooser_o = i; break;
                  }
        break;
        case SDL_CONTROLLERBUTTONDOWN:
            ui_input_gp |= 1;
            switch(event.cbutton.button) {
                case SDL_CONTROLLER_BUTTON_A:
                case SDL_CONTROLLER_BUTTON_B:
                case SDL_CONTROLLER_BUTTON_X:
                case SDL_CONTROLLER_BUTTON_Y: chooser_p = 1; break;
                case SDL_CONTROLLER_BUTTON_DPAD_UP: goto left;
                case SDL_CONTROLLER_BUTTON_DPAD_DOWN: goto right;
                case SDL_CONTROLLER_BUTTON_DPAD_LEFT: goto left;
                case SDL_CONTROLLER_BUTTON_DPAD_RIGHT: goto right;
            }
        break;
        case SDL_CONTROLLERBUTTONUP:
            ui_input_gp |= 1; chooser_p = 0;
            switch(event.cbutton.button) {
                case SDL_CONTROLLER_BUTTON_A:
                case SDL_CONTROLLER_BUTTON_B:
                case SDL_CONTROLLER_BUTTON_X:
                case SDL_CONTROLLER_BUTTON_Y: goto dosel;
            }
        break;
        case SDL_CONTROLLERAXISMOTION:
            ui_input_gp |= 1;
            if(event.caxis.axis == SDL_CONTROLLER_AXIS_LEFTY || event.caxis.axis == SDL_CONTROLLER_AXIS_RIGHTY) {
                if(event.caxis.value < -main_gptres) goto left;
                if(event.caxis.value > main_gptres) goto right;
            }
            if(event.caxis.axis == SDL_CONTROLLER_AXIS_LEFTX || event.caxis.axis == SDL_CONTROLLER_AXIS_RIGHTX) {
                if(event.caxis.value < -main_gptres) goto left;
                if(event.caxis.value > main_gptres) goto right;
            }
        break;
    }
    return 1;
}

/**
 * View layer
 */
void chooser_view(SDL_Rect *dst)
{
    world_sprite_t *s;
    world_chropt_t *list;
    int i, j, k = 0;

    if(!main_draw || chooser_idx < 0 || chooser_idx >= world.numchr || !chooser_regs || !world.choosers || !world.choosers[chooser_idx].opts ||
        !world.attrs || !world.players || !world.players[0].data.attrs) return;
    list = world.choosers[chooser_idx].opts;
    memset(&chooser_dst, 0, sizeof(chooser_dst));
    for(j = 0; j < 14; j++)
        for(i = 0; i < world.choosers[chooser_idx].numopts; i++) {
            if(!j) { list[i].dst.x = list[i].dst.y = 0; list[i].dst.w = list[i].dst.h = -1; }
            if(list[i].type == j &&
              (list[i].req1.type == 2 ||
              (list[i].req1.type < 2 && world.players[0].data.attrs[world.attrs[list[i].req1.attr].idx] == list[i].req1.value) ||
              (list[i].req1.type > 2 && chooser_regs[list[i].req1.type - 2] == list[i].req1.value)) &&
              (list[i].req2.type == 2 ||
              (list[i].req2.type < 2 && world.players[0].data.attrs[world.attrs[list[i].req2.attr].idx] > list[i].req2.value) ||
              (list[i].req2.type > 2 && chooser_regs[list[i].req2.type - 2] > list[i].req2.value))) {
                if(j < 13) {
                    s = spr_get(SPR_UI, i != chooser_o ? list[i].data.spr.n.idx : (chooser_p ? list[i].data.spr.p.idx : list[i].data.spr.s.idx), 0);
                    if(!s) continue;
                    k++;
                    list[i].dst.w = s->w; list[i].dst.h = s->h;
                    switch(j) {
                        case 0: case 1: case 2: case 3: case 7: case 8: case 9:
                            chooser_dst[j].w += (chooser_dst[j].w ? world.choosers[chooser_idx].h : 0) + s->w;
                            if(s->h > chooser_dst[j].h) chooser_dst[j].h = s->h;
                        break;
                        default:
                            chooser_dst[j].h += (chooser_dst[j].h ? world.choosers[chooser_idx].v : 0) + s->h;
                            if(s->w > chooser_dst[j].w) chooser_dst[j].w = s->w;
                        break;
                    }
                } else {
                    k++;
                    list[i].dst.x = dst->x + (dst->w * list[i].data.coord.x1 + 50) / 100;
                    list[i].dst.y = dst->y + (dst->h * list[i].data.coord.y1 + 50) / 100;
                    list[i].dst.w = dst->x + (dst->w * list[i].data.coord.x2 + 50) / 100 - list[i].dst.x;
                    list[i].dst.h = dst->y + (dst->h * list[i].data.coord.y2 + 50) / 100 - list[i].dst.y;
                }
            }
        }
    /* failsafe, if no options are available, close chooser */
    if(!k) { chooser_free(); return; }
    for(j = 0; j < 14; j++)
        for(i = 0; i < world.choosers[chooser_idx].numopts; i++)
            if(list[i].type == j && list[i].dst.w > 0 && list[i].dst.h > 0) {
                switch(j) {
                    case 0:
                        list[i].dst.x = dst->x + (dst->w - chooser_dst[j].w) / 2 + chooser_dst[j].x;
                        list[i].dst.y = dst->y + (dst->h - list[i].dst.h) / 2;
                        chooser_dst[j].x += world.choosers[chooser_idx].h + list[i].dst.w;
                    break;
                    case 1:
                        list[i].dst.x = dst->x + chooser_dst[j].x + world.choosers[chooser_idx].l;
                        list[i].dst.y = dst->y + world.choosers[chooser_idx].t;
                        chooser_dst[j].x += world.choosers[chooser_idx].h + list[i].dst.w;
                    break;
                    case 2:
                        list[i].dst.x = dst->x + (dst->w - chooser_dst[j].w) / 2 + chooser_dst[j].x;
                        list[i].dst.y = dst->y + world.choosers[chooser_idx].t;
                        chooser_dst[j].x += world.choosers[chooser_idx].h + list[i].dst.w;
                    break;
                    case 3:
                        list[i].dst.x = dst->x + dst->w - chooser_dst[j].w + chooser_dst[j].x - world.choosers[chooser_idx].l;
                        list[i].dst.y = dst->y + world.choosers[chooser_idx].t;
                        chooser_dst[j].x += world.choosers[chooser_idx].h + list[i].dst.w;
                    break;
                    case 4:
                        list[i].dst.x = dst->x + dst->w - list[i].dst.w - world.choosers[chooser_idx].l;
                        list[i].dst.y = dst->y + chooser_dst[j].y + world.choosers[chooser_idx].t + chooser_dst[3].h;
                        chooser_dst[j].y += world.choosers[chooser_idx].v + list[i].dst.h;
                    break;
                    case 5:
                        list[i].dst.x = dst->x + dst->w - list[i].dst.w - world.choosers[chooser_idx].l;
                        list[i].dst.y = dst->y + (dst->h - chooser_dst[j].h) / 2 + chooser_dst[j].y;
                        chooser_dst[j].y += world.choosers[chooser_idx].v + list[i].dst.h;
                    break;
                    case 6:
                        list[i].dst.x = dst->x + dst->w - list[i].dst.w - world.choosers[chooser_idx].l;
                        list[i].dst.y = dst->y + dst->h - chooser_dst[j].h + chooser_dst[j].y - world.choosers[chooser_idx].t - chooser_dst[7].h;
                        chooser_dst[j].y += world.choosers[chooser_idx].v + list[i].dst.h;
                    break;
                    case 7:
                        list[i].dst.x = dst->x + dst->w - chooser_dst[j].w + chooser_dst[j].x - world.choosers[chooser_idx].l;
                        list[i].dst.y = dst->y + dst->h - list[i].dst.h - world.choosers[chooser_idx].t;
                        chooser_dst[j].x += world.choosers[chooser_idx].h + list[i].dst.w;
                    break;
                    case 8:
                        list[i].dst.x = dst->x + (dst->w - chooser_dst[j].w) / 2 + chooser_dst[j].x;
                        list[i].dst.y = dst->y + dst->h - list[i].dst.h - world.choosers[chooser_idx].t;
                        chooser_dst[j].x += world.choosers[chooser_idx].h + list[i].dst.w;
                    break;
                    case 9:
                        list[i].dst.x = dst->x + chooser_dst[j].x + world.choosers[chooser_idx].l;
                        list[i].dst.y = dst->y + dst->h - list[i].dst.h - world.choosers[chooser_idx].t;
                        chooser_dst[j].x += world.choosers[chooser_idx].h + list[i].dst.w;
                    break;
                    case 10:
                        list[i].dst.x = dst->x + world.choosers[chooser_idx].l;
                        list[i].dst.y = dst->y + dst->h - chooser_dst[j].h + chooser_dst[j].y - world.choosers[chooser_idx].t - chooser_dst[9].h;
                        chooser_dst[j].y += world.choosers[chooser_idx].v + list[i].dst.h;
                    break;
                    case 11:
                        list[i].dst.x = dst->x + world.choosers[chooser_idx].l;
                        list[i].dst.y = dst->y + (dst->h - chooser_dst[j].h) / 2 + chooser_dst[j].y;
                        chooser_dst[j].y += world.choosers[chooser_idx].v + list[i].dst.h;
                    break;
                    case 12:
                        list[i].dst.x = dst->x + world.choosers[chooser_idx].l;
                        list[i].dst.y = dst->y + chooser_dst[j].y + world.choosers[chooser_idx].t + chooser_dst[1].h;
                        chooser_dst[j].y += world.choosers[chooser_idx].v + list[i].dst.h;
                    break;
                }
                if(j < 13) {
                    s = spr_get(SPR_UI, i != chooser_o ? list[i].data.spr.n.idx : (chooser_p ? list[i].data.spr.p.idx : list[i].data.spr.s.idx), 0);
                    if(s) spr_render(list[i].dst.x, list[i].dst.y, s, ui_anim(s->t, s->f, -1), 0, s->w, s->h, game_a);
                } else if(i == chooser_o) {
                    SDL_SetRenderDrawColor(renderer, world.colors[COLOR_SEL] & 0xff, (world.colors[COLOR_SEL] << 8) & 0xff,
                        (world.colors[COLOR_SEL] << 16) & 0xff, (world.colors[COLOR_SEL] << 24) & 0xff);
                    SDL_RenderDrawLine(renderer, list[i].dst.x + 1, list[i].dst.y, list[i].dst.x + list[i].dst.w - 1, list[i].dst.y);
                    SDL_RenderDrawLine(renderer, list[i].dst.x, list[i].dst.y + 1, list[i].dst.x, list[i].dst.y + list[i].dst.h - 1);
                    SDL_RenderDrawLine(renderer, list[i].dst.x + list[i].dst.w, list[i].dst.y + 1, list[i].dst.x + list[i].dst.w, list[i].dst.y + list[i].dst.h - 1);
                    SDL_RenderDrawLine(renderer, list[i].dst.x + 1, list[i].dst.y + list[i].dst.h, list[i].dst.x + list[i].dst.w - 1, list[i].dst.y + list[i].dst.h);
                    SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
                }
            }
}
