#include <ctype.h>

/* .eq file format:
 * 
 * One setting per line is allowed. On each line, the following is allowed: 
 * "<setting>: <value> <optional comment>". Each "word" on a line must be 
 * separated with at least one whitespace. Leading and trailing whitespace is 
 * ignored. Empty lines are ignored. Comments may be placed on a line on 
 * itself, or after a value.
 * 
 * The following settings are available:
 * 
 * volume
 * bass
 * treble
 * balance
 * channels
 * 
 * The recorder have the following additional settings:
 * 
 * loudness
 * bass_boost
 * auto_volume
 * 
 */

/* should ofcourse be in mpeg.c */
int mpeg_phys2val(int setting, int value)
{
    int result = 0;
    
    switch(setting)
    {
        case SOUND_VOLUME:
            result = value / 2;
            break;
        
        case SOUND_BALANCE:
            result = value / 2;
            break;
        
        case SOUND_BASS:
#ifdef HAVE_MAS3587F
            result = value + 12;
#else
            result = value + 15;
#endif
            break;
        
        case SOUND_TREBLE:
#ifdef HAVE_MAS3587F
            result = value + 12;
#else
            result = value + 15;
#endif
            break;

#ifdef HAVE_MAS3587F
        case SOUND_LOUDNESS:
            result = value;
            break;
            
        case SOUND_SUPERBASS:
            result = value / 10;
            break;
#endif
    }

    return result;
}

int read_line(int fd, char* buffer, int buffer_size)
{
    char ch;
    int i = 0;

    while (i < (buffer_size - 1))
    {
        /* Not the most efficient way to read, but we're usually not reading 
         * large amounts of data.
         * A "real" fgets-like function in file.c would do it better...
         */
        if (1 != read(fd, &ch, 1))
        {
            break;
        }

        buffer[i++] = ch;

        if ('\n' == ch)
        {
          break;
        }
    }

    buffer[i] = 0;
    return i;
}

char* get_word(char* string, char* word, int word_size)
{
    int i = 0;

    while (*string && isspace(*string))
    {
        string++;
    }

    while (*string && !isspace(*string) && (i < (word_size - 1)))
    {
        *word++ = *string++;
    }

    *word = 0;

    return string;
}

bool is_numeric(char* string)
{
    if (!*string)
    {
      return false;
    }

    if ('-' == *string)
    {
      string++;
    }

    while (*string)
    {
        if (!isdigit(*string++))
        {
            return false;
        }
    }

    return true;
}


void show_eq_msg(char* line_1, char* line_2, bool error)
{
    lcd_clear_display();
    lcd_puts(0, 0, line_1);
    lcd_puts(0, 1, line_2);
    lcd_update();
    sleep(error ? (HZ * 2) : (HZ / 2));
}

void set_eq_sound(char* setting_name, char* value_string, int sound_type, int* setting_value)
{
    char buffer[16];
    int value;
    
    if (is_numeric(value_string))
    {
        /* Really, atoi needs to be improved... :) */
        bool sign = 1;

        if ('-' == value_string[0])
        {
            value_string[0] = '0';
            sign = -1;
        }

        value = atoi(value_string) * sign;
    }
    else
    {
        show_eq_msg("Not number:", value_string, true);
        return;
    }

    value = mpeg_phys2val(sound_type, value);

    if ((value > mpeg_sound_max(sound_type)) 
        || (value < mpeg_sound_min(sound_type)))
    {
        value = mpeg_sound_default(sound_type);
        show_eq_msg("Using def.:", setting_name, true);
    }

    *setting_value = value;
    mpeg_sound_set(sound_type, value);
    snprintf(buffer, sizeof(buffer), "%d %s", 
        mpeg_val2phys(sound_type, value), mpeg_sound_unit(sound_type));
    show_eq_msg(setting_name, buffer, false);
}

bool settings_load_eq(char* file)
{
    int fd;

    fd = open(file, O_RDONLY);

    if (-1 != fd)
    {
        char buffer[128];
        char setting[32];
        char value[64];     /* Need to handle file names? */
        char* cursor;
        int len;

        while (read_line(fd, buffer, sizeof(buffer)) > 0)
        {
            cursor = buffer;
            cursor = get_word(cursor, setting, sizeof(setting));
            len = strlen(setting);

            if ((0 == len) || ('#' == *setting))
            {
              /* Comment or empty line */
              continue;
            }
            
            len--;
            
            if (':' != setting[len])
            {
                show_eq_msg("Not known:", setting, true);
                continue;
            }

            setting[len] = 0;   /* Remove ':' */

            cursor = get_word(cursor, value, sizeof(value));

            if ((0 == strlen(value)) || ('#' == *value))
            {
                show_eq_msg("No value:", value, true);
            }
            
            if (!strcasecmp(setting, "volume"))
            {
                set_eq_sound(setting, value, SOUND_VOLUME, &global_settings.volume);
            }
            else if (!strcasecmp(setting, "bass"))
            {
                set_eq_sound(setting, value, SOUND_BASS, &global_settings.bass);
            }
            else if (!strcasecmp(setting, "treble"))
            {
                set_eq_sound(setting, value, SOUND_TREBLE, &global_settings.treble);
            }
            else if (!strcasecmp(setting, "balance"))
            {
                set_eq_sound(setting, value, SOUND_BALANCE, &global_settings.balance);
                /* This call is needed to make the balance change to actually 
                 * take effect (on players at least). mpeg_sound_set should 
                 * fall through to SOUND_VOLUME on SOUND_BALANCE. Or 
                 * something like that...
                 */
                mpeg_sound_set(SOUND_VOLUME, global_settings.volume);
            }
            else if (!strcasecmp(setting, "channels"))
            {
                set_eq_sound(setting, value, SOUND_CHANNELS, &global_settings.bass);
            }
#ifdef HAVE_MAS3587F
            else if (!strcasecmp(setting, "loudness"))
            {
                set_eq_sound(setting, value, SOUND_LOUDNESS, &global_settings.loudness);
            }
            else if (!strcasecmp(setting, "bass_boost"))
            {
                set_eq_sound(setting, value, SOUND_SUPERBASS, &global_settings.bass_boost);
            }
            else if (!strcasecmp(setting, "auto_volume"))
            {
                set_eq_sound(setting, value, SOUND_AVC, &global_settings.avc);
            }
#endif
            else
            {
                show_eq_msg("Not known:", setting, true);
            }
        }

        close(fd);
        return true;
    }
    else
    {
        show_eq_msg("Not found:", file, true);
    }

    return false;
}
