/******************************************************************************
*
* Copyright (C) 2006-2017  Brian Berlin
* 
* 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, see <http://www.gnu.org/licenses/>
*
******************************************************************************
*
* FILENAME: palette.c
*
* DESCRIPTION:  This handles creation, saving, and recalling of color palettes
*
* AUTHORS:  bberlin
*
* CHANGE LOG
*
*  VER     DATE     CHANGED BY   DESCRIPTION OF CHANGE
* ------  --------  ----------   ------------------------------------
* 0.2     01/03/06  bberlin      Creation
* 0.4.0   06/12/06  bberlin      Change phase shift, saturation, and phase
*                                  multiplier of internal default palette
******************************************************************************/
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <stdio.h>
#include "util.h"
#include "logger.h"
#include "katconfig.h"
#include "palette.h"

#define CLIP_VAR(x) \
  if (x > 0xff) \
    x = 0xff; \
  if (x < 0) \
    x = 0

static char msg[1100];

static int recall_flag;

void make_default_palette (int *pal) {

    int red[256], green[256], blue[256];
    int i, j;
    const double colf = 0.090;
    int colshift = 54;
    const double redf = 0.30;
    const double greenf = 0.59;
    const double bluef = 0.11;
    int r, g, b;
    int white = 0xf0;
    double angle;
    int y, r1, g1, b1;

  for (i = 0; i < 0x10; i++)
  {
    if (i == 0)
    {
      r = g = b = 0;
    }
    else
    {
      angle = 3.14159 * ((double) i * (5.0 / 34.0) - (double) colshift * 0.01);
      r = (int)((colf / redf) * cos(angle) * (white));
      g = (int)((colf / greenf) * cos(angle + 3.14159 * (2.0 / 3)) * (white));
      b = (int)((colf / bluef) * cos(angle + 3.14159 * (4.0 / 3)) * (white));
    }
    for (j = 0; j < 0x10; j++)
    {

      y = (white * j) / 0xf;
      r1 = y + r;
      g1 = y + g;
      b1 = y + b;
      CLIP_VAR(r1);
      CLIP_VAR(g1);
      CLIP_VAR(b1);
      red[i * 16 + j] = r1;
      green[i * 16 + j] = g1;
      blue[i * 16 + j] = b1;
    }
  }
  for (i = 0; i < 0x100; i++)
  {
    pal[i] = (red[i] << 16) + (green[i] << 8) + (blue[i] << 0);
  }
} /* end make_default_palette */

/******************************************************************************
**  Function   :  convert_palette
**                            
**  Objective  :  This function converts the file format from atari800 to db
**
**  Parameters :  old_file  - name of file containing atari800 binary array
**                new_name  - name of palette to store
**                                                
**  return     :  Error code
**      
******************************************************************************/
int convert_palette ( char *old_file, char *new_name ) {

    int pal[256];
    int i,j,c;
    FILE *fp;

    if (!old_file || !strlen(old_file))
        return PALETTE_IMPORT_ERR_OPEN;
    if (!new_name || !strlen(new_name))
        return PALETTE_IMPORT_ERR_READ;
    if (config_palette_exists(config_get_global_table(), new_name))
        return PALETTE_IMPORT_ERR_EXISTS;

    /*
     * Open the atari800 palette and get values
     */
    if ((fp = fopen(old_file,"rb")) == NULL) {
        sprintf ( msg, "Could not open Atari800 Pallete file: %s", old_file );
        logger_log_message ( LOG_ERROR, msg, "" );
        return PALETTE_IMPORT_ERR_OPEN;
    }
    for (i = 0; i < 256; ++i ) {
        pal[i] = 0;
        for (j = 16; j >= 0; j -= 8) {
            c = fgetc(fp);
            if (c == EOF) {
                fclose(fp);
                sprintf ( msg, "Could not read Atari800 Pallete file: %s", old_file );
                logger_log_message ( LOG_ERROR, msg, "" );
                return PALETTE_IMPORT_ERR_READ;
            }
            pal[i] |= c << j;
        }
    }
    fclose(fp);

    /*
     * Now save to the new file as kat5200 palette
     */
    config_save_palette ( config_get_global_table(), new_name, pal );

    return PALETTE_IMPORT_OK;

} /* end convert_palette */

/******************************************************************************
**  Function   :  save_a800_pal
**                            
**  Objective  :  This function saves the palette as an Atari800 style file
**
**  Parameters :  file  - name of file to save Atari 800 palette to
**                pal   - palette to save
**                                                
**  return     :  Error code
**      
******************************************************************************/
int save_a800_pal ( char *file, int *pal ) {

    int i,j;
    FILE *fp;

    /*
     * Open the atari800 palette and get values
     */
    if ((fp = fopen(file,"wb")) == NULL) {
        sprintf ( msg, "Could not open Atari800 Pallete file: %s", file );
        logger_log_message ( LOG_ERROR, msg, "" );
        return -1;
    }
    for (i = 0; i < 256; ++i ) {
        for (j = 16; j >= 0; j -= 8) {
            fputc(pal[i]>>j, fp);
        }
    }
    fclose(fp);

    return 0;

} /* end save_a800_pal */

/******************************************************************************
**  Function   :  convert_kat_palette
**                            
**  Objective  :  This function converts the file format from xml to atari800
**
**  Parameters :  old_name  - name of palette containing kat5200 palette
**                new_file  - name of file to store value to
**                                                
**  return     :  Error code
**      
******************************************************************************/
int convert_kat_palette ( char *old_name, char *new_file ) {

    int pal[256];

    /*
     * Now save to the new file as kat5200 palette
     */
    if (config_load_palette ( config_get_global_table(), old_name, pal ))
        return -1;

    if ( save_a800_pal ( new_file, pal ) )
        return -1;

    return 0;

} /* end convert_kat_palette */
