/*
 * tngp/credits.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 Credits screen
 *
 */

#include "tngp.h"

SDL_Texture *credits_bg = NULL, *credits_fg = NULL;
SDL_Rect credits_bgsrc, credits_bgdst, credits_src, credits_dst;
int credits_fade, credits_a;
uint32_t credits_fadeb;
extern char *copyright[3];

/**
 * Initialize credits
 */
void credits_init()
{
    ssfn_t *hdrfnt, *txtfnt;
    ssfn_buf_t buf = { 0 };
    uint8_t *pixels1, *pixels2;
    int i, j, p, b, x, y, w, h;
    char *str;

    hdrfnt = font_get(FNT_CRD_HDR);
    txtfnt = font_get(FNT_CRD_NAME);
    for(i = scr_h = 0; i < WORLD_NUMCRDS; i++) {
        if(world.crds[i].num)
            scr_h += 2 * world.fonts[FNT_CRD_HDR].size + (world.crds[i].num + 1) * world.fonts[FNT_CRD_NAME].size + 4;
    }
    scr_h += 2 * world.fonts[FNT_CRD_HDR].size + 3 * 16 + 4;
    if(scr_h > 4096) scr_h = 4096;

    credits_bgsrc.x = credits_bgsrc.y = credits_bgdst.x = credits_bgdst.y = 0;
    credits_bgdst.w = win_w; credits_bgdst.h = win_h;
    credits_bg = spr_getbg(world.crdimage.idx, &x, &y);
    if(credits_bg) {
        if(!(world.hastitle & 2)) {
            ui_fit(x, y, win_w, win_h, &credits_bgsrc.w, &credits_bgsrc.h);
            credits_bgsrc.x = (x - credits_bgsrc.w) / 2; credits_bgsrc.y = (y - credits_bgsrc.h) / 2;
        } else {
            credits_bgsrc.w = x; credits_bgsrc.h = y;
            ui_fit(win_w, win_h, x, y, &credits_bgdst.w, &credits_bgdst.h);
        }
    } else {
        x = win_w; y = win_h;
    }
    /* failsafe */
    if(!credits_bgdst.w || !credits_bgdst.h) { credits_bgdst.w = win_w; credits_bgdst.h = win_h; }
    credits_bgdst.x = credits_dst.x = (win_w - credits_bgdst.w) / 2; credits_bgdst.y = (win_h - credits_bgdst.h) / 2;
    credits_src.w = credits_dst.w = scr_w = credits_bgdst.w; credits_src.y = 0; credits_dst.y = credits_bgdst.y + credits_bgdst.h;
    credits_src.h = credits_dst.h = 1;
    credits_fg = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ABGR8888, SDL_TEXTUREACCESS_STREAMING, x, y);
    if(credits_fg) {
        SDL_SetTextureBlendMode(credits_fg, SDL_BLENDMODE_BLEND);
        if(credits_bg) SDL_LockTexture(credits_bg, NULL, (void**)&pixels1, &b);
        SDL_LockTexture(credits_fg, NULL, (void**)&pixels2, &p);
        memset(pixels2, 0, p * y);
        if(credits_bg) {
            memcpy(pixels2, pixels1, p * 32);
            memcpy(pixels2 + p * (y - 32), pixels1 + b * (y - 32), p * 32);
        }
        for(j = 0; j < 32; j++)
            for(i = 0; i < p; i += 4) {
                pixels2[j * p + i + 3] = (32 - j) * 255 / 32;
                pixels2[(y - 32 + j) * p + i + 3] = j * 255 / 32;
            }
        SDL_UnlockTexture(credits_fg);
        if(credits_bg) SDL_UnlockTexture(credits_bg);
    }

    screen = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ABGR8888, SDL_TEXTUREACCESS_STREAMING, scr_w, scr_h);
    if(screen) {
        SDL_SetTextureBlendMode(screen, SDL_BLENDMODE_BLEND);
        SDL_LockTexture(screen, NULL, (void**)&buf.ptr, &p);
        memset(buf.ptr, 0, p * scr_h);
        buf.p = p; buf.w = scr_w; buf.h = scr_h; j = y = 0;
        if(world.text)
            for(j = y = 0; j < WORLD_NUMCRDS && y < scr_h; j++) {
                if(!world.crds[j].num || !world.crds[j].names) continue;
                str = world.text[GAME_CRD_GAME + j];
                if(!str || !*str) continue;
                ssfn_bbox(hdrfnt, str, &w, &h, &p, &b);
                buf.fg = world.colors[COLOR_TITSH];
                buf.x = (scr_w - w) / 2 + 4; buf.y = y + b + 4;
                if(buf.y >= scr_h) break;
                while(*str && ((i = ssfn_render(hdrfnt, &buf, str)) > 0 || i == SSFN_ERR_NOGLYPH)) str += (i < 1 ? 1 : i);
                buf.fg = world.colors[COLOR_CRD_HDR];
                buf.x = (scr_w - w) / 2; buf.y = y + b;
                str = world.text[GAME_CRD_GAME + j];
                while(*str && ((i = ssfn_render(hdrfnt, &buf, str)) > 0 || i == SSFN_ERR_NOGLYPH)) str += (i < 1 ? 1 : i);
                y += world.fonts[FNT_CRD_HDR].size + world.fonts[FNT_CRD_NAME].size;
                if(y >= scr_h) break;
                for(x = 0; x < world.crds[j].num && y < scr_h; x++, y += world.fonts[FNT_CRD_NAME].size) {
                    str = world.crds[j].names[x];
                    if(!str || !*str) break;
                    ssfn_bbox(txtfnt, str, &w, &h, &p, &b);
                    buf.fg = world.colors[COLOR_TITSH];
                    buf.x = (scr_w - w) / 2 + 2; buf.y = y + b + 2;
                    if(buf.y >= scr_h) break;
                    while(*str && ((i = ssfn_render(txtfnt, &buf, str)) > 0 || i == SSFN_ERR_NOGLYPH)) str += (i < 1 ? 1 : i);
                    str = world.crds[j].names[x];
                    buf.fg = world.colors[COLOR_CRD_NAME];
                    buf.x = (scr_w - w) / 2; buf.y = y + b;
                    while(*str && ((i = ssfn_render(txtfnt, &buf, str)) > 0 || i == SSFN_ERR_NOGLYPH)) str += (i < 1 ? 1 : i);
                }
                y += world.fonts[FNT_CRD_HDR].size;
            }
        y += world.fonts[FNT_CRD_HDR].size;
        txtfnt = font_get(FNT_LAST);
        for(x = 0; x < 3 && y < scr_h; x++, y += 16) {
            str = copyright[x];
            ssfn_bbox(txtfnt, str, &w, &h, &p, &b);
            buf.fg = world.colors[COLOR_TITSH];
            buf.x = (scr_w - w) / 2 + 2; buf.y = y + b + 2;
            if(buf.y >= scr_h) break;
            while(*str && ((i = ssfn_render(txtfnt, &buf, str)) > 0 || i == SSFN_ERR_NOGLYPH)) str += (i < 1 ? 1 : i);
            str = copyright[x];
            buf.fg = world.colors[COLOR_CRD_NAME];
            buf.x = (scr_w - w) / 2; buf.y = y + b;
            while(*str && ((i = ssfn_render(txtfnt, &buf, str)) > 0 || i == SSFN_ERR_NOGLYPH)) str += (i < 1 ? 1 : i);
        }
        SDL_UnlockTexture(screen);
    } else { main_switchtab(TAB_EXIT); return; }

    if(world.crdmusic >= 0 && world.crdmusic < world.nummusic && world.music)
        media_playmus(NULL, &world.music[world.crdmusic]);
    credits_fade = 1; credits_a = 0; credits_fadeb = SDL_GetTicks();
}

/**
 * Free resources
 */
void credits_free()
{
    if(credits_bg) { SDL_DestroyTexture(credits_bg); credits_bg = NULL; }
    if(credits_fg) { SDL_DestroyTexture(credits_fg); credits_fg = NULL; }
    if(screen) { SDL_DestroyTexture(screen); screen = NULL; }
}

/**
 * Controller
 */
int credits_ctrl()
{
    switch(event.type) {
        case SDL_KEYDOWN:
        case SDL_MOUSEBUTTONDOWN:
        case SDL_CONTROLLERBUTTONDOWN:
        case SDL_FINGERDOWN:
        case SDL_JOYBUTTONDOWN:
            media_stopmus(250); credits_fade = -1; credits_fadeb = SDL_GetTicks();
        break;
    }
    return 1;
}

/**
 * View layer
 */
void credits_view()
{
    uint32_t now = SDL_GetTicks();

    if(!main_draw) return;
    if(credits_fade) {
        if(credits_fade > 0) {
            credits_a = (now - credits_fadeb) * 255 / 500;
            if(credits_a >= 255) { credits_a = 255; credits_fade = 0; }
        } else {
            credits_a = 255 - ((now - credits_fadeb) * 255 / 250);
            if(credits_a <= 0) main_switchtab(TAB_EXIT);
        }
        if(credits_bg && (credits_fade < 0 || world.crdimage.idx != world.bgimage.idx))
            SDL_SetTextureAlphaMod(credits_bg, credits_a);
        if(credits_fg) SDL_SetTextureAlphaMod(credits_fg, credits_a);
        if(screen) SDL_SetTextureAlphaMod(screen, credits_a);
    }
    if(credits_dst.y > credits_bgdst.y) {
        credits_dst.y--;
        credits_src.h = credits_dst.h = (credits_bgdst.y + credits_bgdst.h - credits_dst.y > scr_h ? scr_h :
            credits_bgdst.y + credits_bgdst.h - credits_dst.y);
    } else {
        credits_src.y++;
        credits_src.h = credits_dst.h = (credits_src.y + credits_bgdst.h > scr_h ? scr_h - credits_src.y : credits_bgdst.h);
    }
    if(credits_src.h < 1) main_switchtab(TAB_EXIT);
    if(credits_bg)
        SDL_RenderCopy(renderer, credits_bg, &credits_bgsrc, &credits_bgdst);
    if(screen)
        SDL_RenderCopy(renderer, screen, &credits_src, &credits_dst);
    if(credits_fg)
        SDL_RenderCopy(renderer, credits_fg, &credits_bgsrc, &credits_bgdst);
}
