/*
 * SingerConfig.java
 * Copyright (c) 2008 kbinani
 *
 * This file is part of jp.sourceforge.lipsync.vsq.
 *
 * jp.sourceforge.lipsync.vsq is free software; you can redistribute it and/or
 * modify it under the terms of the BSD License.
 *
 * jp.sourceforge.lipsync.vsq 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.
 */
package jp.sourceforge.lipsync.vsq;

import java.util.*;
import java.io.*;
import jp.sourceforge.lipsync.bocoree.*;

public class SingerConfig {
    public String ID = "VOCALOID:VIRTUAL:VOICE";
    public String FORMAT = "2.0.0.0";
    public String VOICEIDSTR = "";
    public String VOICENAME = "Miku";
    public int Breathiness = 0;
    public int Brightness = 0;
    public int Clearness = 0;
    public int Opening = 0;
    public int GenderFactor = 0;
    public int Original = 0;

    public static void decode_vvd_bytes( Vector dat ) {
        for ( int i = 0; i < dat.size(); i++ ) {
            byte b = (Byte)dat.get( i );
            byte M = (byte)(b >> 4);
            byte L = (byte)(b - (M << 4));
            byte newM = endecode_vvd_m( M );
            byte newL = endecode_vvd_l( L );
            dat.set( i, (byte)((newM << 4) | newL) );
        }
    }

    private static byte endecode_vvd_l( byte value ) {
        switch ( value ) {
            case 0x0:
                return 0xa;
            case 0x1:
                return 0xb;
            case 0x2:
                return 0x8;
            case 0x3:
                return 0x9;
            case 0x4:
                return 0xe;
            case 0x5:
                return 0xf;
            case 0x6:
                return 0xc;
            case 0x7:
                return 0xd;
            case 0x8:
                return 0x2;
            case 0x9:
                return 0x3;
            case 0xa:
                return 0x0;
            case 0xb:
                return 0x1;
            case 0xc:
                return 0x6;
            case 0xd:
                return 0x7;
            case 0xe:
                return 0x4;
            case 0xf:
                return 0x5;
        }
        return 0x0;
    }

    private static byte endecode_vvd_m( byte value ) {
        switch ( value ) {
            case 0x0:
                return 0x1;
            case 0x1:
                return 0x0;
            case 0x2:
                return 0x3;
            case 0x3:
                return 0x2;
            case 0x4:
                return 0x5;
            case 0x5:
                return 0x4;
            case 0x6:
                return 0x7;
            case 0x7:
                return 0x6;
            case 0x8:
                return 0x9;
            case 0x9:
                return 0x8;
            case 0xa:
                return 0xb;
            case 0xb:
                return 0xa;
            case 0xc:
                return 0xd;
            case 0xd:
                return 0xc;
            case 0xe:
                return 0xf;
            case 0xf:
                return 0xe;
        }
        return 0x0;
    }

    public SingerConfig( String file, int original ) throws FileNotFoundException, IOException {
        Original = original;
        FileInputStream fs = new FileInputStream( file );
        File f = new File( file );
        int length = (int)f.length();
        byte[] tdat = new byte[length];
        fs.read( tdat, 0, length );
        Vector dat = new Vector();
        decode_vvd_bytes( dat );
        for ( int i = 0; i < dat.size() - 1; i++ ) {
            tdat[i] = (Byte)dat.get( i );
        }
        for ( int i = 0; i < tdat.length - 1; i++ ) {
            byte b = tdat[i];
            if ( b == 0x17 && b == 0x10 ) {
                tdat[i] = 0x0d;
                tdat[i + 1] = 0x0a;
            }
        }
        String str = cp932.convert( tdat );
        String crlf = Character.toString( (char)0x0d ) + Character.toString( (char)0x0a );
        String[] spl = str.split( crlf );

        for ( int i = 0; i < spl.length; i++ ) {
            String s = spl[i];
            int first = s.indexOf( '"' );
            int first_end = get_quated_String( s, first );
            int second = s.indexOf( '"', first_end + 1 );
            int second_end = get_quated_String( s, second );
            char[] chs = s.toCharArray();
            String id = new String( chs, first, first_end - first + 1 );
            String value = new String( chs, second, second_end - second + 1 );
            id = id.substring( 1, id.length() - 2 );
            value = value.substring( 1, value.length() - 2 );
            value = value.replace( "\\\"", "\"" );
            if ( id.equals( "ID" ) ) {
                ID = value;
            } else if ( id.equals( "FORMAT" ) ) {
                FORMAT = value;
            } else if ( id.equals( "VOICEIDSTR" ) ) {
                VOICEIDSTR = value;
            } else if ( id.equals( "VOICENAME" ) ) {
                VOICENAME = value;
            } else if ( id.equals( "Breathiness" ) ) {
                try {
                    Breathiness = Integer.parseInt( value );
                } catch ( Exception e ) {
                }
            } else if ( id.equals( "Brightness" ) ) {
                try {
                    Brightness = Integer.parseInt( value );
                } catch ( Exception e ) {
                }
            } else if ( id.equals( "Clearness" ) ) {
                try {
                    Clearness = Integer.parseInt( value );
                } catch ( Exception e ) {
                }
            } else if ( id.equals( "Opening" ) ) {
                try {
                    Opening = Integer.parseInt( value );
                } catch ( Exception e ) {
                }
            } else if ( id.equals( "Gender:Factor" ) ) {
                try {
                    GenderFactor = Integer.parseInt( value );
                } catch ( Exception e ) {
                }
            }
        }
    }


/// <summary>
/// 位置positionにある'"'から，次に現れる'"'の位置を調べる．エスケープされた\"はスキップされる．'"'が見つからなかった場合-1を返す
/// </summary>
/// <param name="s"></param>
/// <param name="position"></param>
/// <returns></returns>
    private static int get_quated_String( String s, int position ) {
        if ( position < 0 ) {
            return -1;
        }

        char[] chs = s.toCharArray();
        if ( position >= chs.length ) {
            return -1;
        }

        if ( chs[position] != '"' ) {
            return -1;
        }

        int end = -1;
        for ( int i = position + 1; i <
                chs.length; i++ ) {
            if ( chs[i] == '"' && chs[i - 1] != '\\' ) {
                end = i;
                break;
            }
        }
        return end;
    }

    // ここ注意！！
    public String[] toStringEx() {
        Vector<String> ret = new Vector<String>();
        ret.add( "\"ID\":=:\"" + ID + "\"" );
        ret.add( "\"FORMAT\":=:\"" + FORMAT + "\"" );
        ret.add( "\"VOICEIDSTR\":=:\"" + VOICEIDSTR + "\"" );
        ret.add( "\"VOICENAME\":=:\"" + VOICENAME.replace( "\"", "\\\"" ) + "\"" );
        ret.add( "\"Breathiness\":=:\"" + Breathiness + "\"" );
        ret.add( "\"Brightness\":=:\"" + Brightness + "\"" );
        ret.add( "\"Clearness\":=:\"" + Clearness + "\"" );
        ret.add( "\"Opening\":=:\"" + Opening + "\"" );
        ret.add( "\"Gender:Factor\":=:\"" + GenderFactor + "\"" );
        return ret.toArray( new String[]{} );
    }

    /*public property int Original {
    get         {
    return m_original;
    }
    set         {
    m_original = value;
    }
    };*/

    /*public property String ID     {
    get         {
    return m_id;
    }
    set        {
    m_id = value;
    }
    };*/

    /*public property String FORMAT {
    get         {
    return m_format;
    }
    set         {
    m_format = value;
    }
    };*/

    /*public property String VOICEIDSTR {
    get         {
    return m_voiceidstr;
    }
    set         {
    m_voiceidstr = value;
    }
    };*/

    /*public proprety String VOICENAME {
    get         {
    return m_voicename;
    }
    set         {
    m_voicename = value;
    }
    };*/

    /*public property int Breathiness     {
    get         {
    return m_breathiness;
    }
    set         {
    m_breathiness = value;
    }
    };*/

    /*public property int Brightness     {
    get         {
    return m_brightness;
    }
    set         {
    m_brightness = value;
    }
    };*/

    /*public property int Clearness     {
    get         {
    return m_clearness;
    }
    set         {
    m_clearness = value;
    }
    };*/

    /*public proprety int Opening     {
    get         {
    return m_opening;
    }
    set         {
    m_opening = value;
    }
    };*/

    /*public property int GenderFactor     {
    get         {
    return m_gender_factor;
    }
    set         {
    m_gender_factor = value;
    }
    };*/
}