/*
 * mtsedit/search.c
 *
 * Copyright (C) 2019 bzt (bztsrc@gitlab)
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use, copy,
 * modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 * @brief Search Block window
 *
 */

#include "main.h"

int numresults, *results = NULL, line, overblk = -1, searchscr = 0;
int searchlen = 0, searchpos = 0;
char search[256] = { 0 }, cur[2] = {0, 0};

/**
 * Redraw the Search Block window
 */
void search_redraw()
{
    int i;
    SDL_Rect rect;

    rect.x = 36; rect.y = 0; rect.w = screen->w - 36; rect.h = screen->h - font->height;
    SDL_FillRect(screen, &rect, theme[THEME_BG]);

    strmaxw = screen->w - 5;
    sdlprint((screen->w - 47 - strlen(lang[ADDBLOCKS]) * (font->width+1)) / 2 + 47, 4, THEME_INPUT, THEME_BG, lang[ADDBLOCKS]);
    rect.y = 12 + font->height;
    sdlprint(42, rect.y, THEME_FG, THEME_BG, lang[SEARCH]);
    rect.x = 160; rect.w = screen->w - 165; rect.h = font->height + 2;
    SDL_FillRect(screen, &rect, theme[THEME_INPBG]);
    strmaxw = screen->w - 5;
    sdlprint(161,rect.y + 1, THEME_INPUT, THEME_INPBG, search);
    cur[0] = search[searchpos] ? search[searchpos] : ' ';
    sdlprint(161 + searchpos * (font->width+1), rect.y + 1, THEME_INPBG, THEME_INPUT, cur);
    rect.x = 42; rect.y = 20 + 2*font->height; rect.w = rect.h = 32;
    if(line != (screen->w - 47) / 32) {
        line = (screen->w - 47) / 32;
        searchscr = 0;
    }
    for(i = searchscr * line; i < numresults && rect.y + 32 < (int)(screen->h - font->height); i++, rect.x += 32) {
        if(rect.x + 32 > screen->w - 5) { rect.x = 42; rect.y += 32; }
        if(rect.y + 32 > (int)(screen->h - font->height)) rect.h = screen->h - font->height - rect.y;
        blk->pixels = results[i] > 0 && results[i] < numblocks && blocks[results[i]].img ? blocks[results[i]].img :
            (uint8_t*)icons->pixels + 32 * icons->pitch;
        SDL_FillRect(screen, &rect, theme[i == overblk ? THEME_INACT : THEME_BG]);
        SDL_BlitSurface(blk, NULL, screen, &rect);
    }
}

/**
 * Search Block window scrolling event handler
 */
void search_scroll(SDL_Event *event)
{
    int i = numresults / line;
    searchscr -= event->wheel.y;
    if(searchscr < 0) searchscr = 0;
    if(searchscr + 1 >= i) searchscr = i - 1;
}

/**
 * Add a block to the palette
 */
void search_addblock(int blk)
{
    int i, j, b;

    if(blk != -1 && blk < numresults) {
        b = results[blk];
        if(!b) return;
        for(j = 1; j < 15 && palette[j] != b; j++);
        for(i = j; i > 1; i--) palette[i] = palette[i - 1];
        palette[1] = b;
        activeblock = 1;
    }
}

/**
 * Search Block window mouse down event handler
 */
void search_mousedown(_unused SDL_Event *event)
{
    if(overblk != -1 && overblk < numresults) {
        search_addblock(overblk);
        status = overblk < 0 || overblk >= numresults || results[overblk] < 0 || results[overblk] >= numblocks ? NULL :
            blocks[results[overblk]].name;
        sdlredraw();
    }
}

/**
 * Search Block mouse over event handler
 */
void search_mouseover(SDL_Event *event)
{
    int i, j = -1;

    if(event->motion.x >= 42 && event->motion.x < screen->w - 5) {
        if(event->motion.y >= (int)(20 + 2*font->height) && event->motion.y < (int)(screen->h - font->height)) {
            i = ((event->motion.x - 42) / 32);
            j = (((event->motion.y - (20 + 2*font->height)) / 32 + searchscr) * line) + (i < line ? i : line);
            if(j >= numresults || !results[j]) j = -1;
        }
    }
    if(j != overblk) {
        overblk = j;
        status = j < 0 || j >= numresults || results[j] < 0 || results[j] >= numblocks ? NULL : blocks[results[j]].name;
        sdlredraw();
    }
}

/**
 * Search Block window keypress event handler
 */
void search_key(SDL_Event *event)
{
    int i, j, l;

    switch(event->type) {
        case SDL_TEXTINPUT:
            j = strlen(event->text.text);
            if(!ctrl && searchlen + j < (int)(sizeof(search))) {
                for(i = searchlen - 1; i >= searchpos; i--) search[i + j] = search[i];
                memcpy(search + searchpos, &event->text.text, j);
                searchpos += j;
                searchlen += j;
                search[searchlen] = 0;
            }
        break;
        case SDL_KEYUP:
            switch (event->key.keysym.sym) {
                case SDLK_BACKSPACE:
                    if(searchpos) {
                        searchpos--;
                        for(i = searchpos; i < searchlen + 1; i++) search[i] = search[i+1];
                        searchlen--;
                    }
                break;
                case SDLK_DELETE:
                    if(searchpos < searchlen) {
                        for(i = searchpos; i < searchlen + 1; i++) search[i] = search[i+1];
                        searchlen--;
                    }
                break;
                case SDLK_UP: searchpos = 0; break;
                case SDLK_DOWN: searchpos = searchlen; break;
                case SDLK_LEFT: if(searchpos) searchpos--; break;
                case SDLK_RIGHT: if(searchpos < searchlen) searchpos++; break;
                case SDLK_TAB:
                case SDLK_RETURN: sdldo(-1); break;
            }
            if(ctrl && event->key.keysym.sym >= SDLK_1 && event->key.keysym.sym <= SDLK_9)
                search_addblock(event->key.keysym.sym - SDLK_1);
        break;
    }
    if(!searchlen) {
        numresults = numblocks - 1;
        for(i = 0; (int)i < numresults; i++) results[i] = i + 1;
    } else {
        for(numresults = 0, i = 1; i < numblocks; i++) {
            l = strlen(blocks[i].name) - searchlen;
            for(j = 0; j < l + 1; j++)
                if(!strncasecmp(blocks[i].name + j, search, searchlen)) {
                    results[numresults++] = i;
                    break;
                }
        }
    }
}
