/*
 * SingerConfigSys.cs
 * Copyright (c) 2009 kbinani
 *
 * This file is part of Boare.Lib.Vsq.
 *
 * Boare.Lib.Vsq is free software; you can redistribute it and/or
 * modify it under the terms of the BSD License.
 *
 * Boare.Lib.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.
 */
using System;
using System.Collections.Generic;
using System.IO;

namespace Boare.Lib.Vsq {

    public class SingerConfigSys {
        private const int MAX_SINGERS = 0x4000;

        private List<SingerConfig> m_installed_singers = new List<SingerConfig>();
        private List<SingerConfig> m_singer_configs = new List<SingerConfig>();

        /// <summary>
        /// 
        /// </summary>
        /// <param name="path_voicedb">音源のデータディレクトリ(ex:"C:\Program Files\VOCALOID2\voicedbdir")</param>
        /// <param name="path_installed_singers">音源のインストールディレクトリ(ex:new string[]{ "C:\Program Files\VOCALOID2\voicedbdir\BXXXXXXXXXXXXXXX", "D:\singers\BNXXXXXXXXXX" })</param>
        public SingerConfigSys( string path_voicedb, string[] path_installed_singers ) {
            m_installed_singers = new List<SingerConfig>();
            m_singer_configs = new List<SingerConfig>();
            String map = Path.Combine( path_voicedb, "voice.map" );
            if ( !File.Exists( map ) ) {
                return;
            }
            using ( FileStream fs = new FileStream( map, FileMode.Open, FileAccess.Read ) ) {
                byte[] dat = new byte[8];
                fs.Seek( 0x20, SeekOrigin.Begin );
                for ( int i = 0; i < MAX_SINGERS; i++ ) {
                    fs.Read( dat, 0, 8 );
                    ulong value = VocaloSysUtil.makelong_le( dat );
                    if ( value >= 1 ) {
                        String vvd = Path.Combine( path_voicedb, "vvoice" + value + ".vvd" );
                        SingerConfig item = SingerConfig.fromVvd( vvd, 0 );
                        item.Program = i;

                        int original = -1;
                        foreach ( SingerConfig sc in m_installed_singers ) {
                            if ( sc.VOICEIDSTR == item.VOICEIDSTR ) {
                                original = sc.Program;
                                break;
                            }
                        }
                        if ( original < 0 ) {
                            foreach ( String ipath in path_installed_singers ) {
                                if ( ipath.EndsWith( item.VOICEIDSTR ) ) {
                                    string[] vvds = Directory.GetFiles( ipath, "*.vvd" );
                                    if ( vvds.Length > 0 ) {
                                        original = m_installed_singers.Count;
                                        SingerConfig installed = SingerConfig.fromVvd( vvds[0], original );
                                        installed.Program = original;
                                        m_installed_singers.Add( installed );
                                        break;
                                    }
                                }
                            }
                        }

                        item.Original = original;
                        m_singer_configs.Add( item );
                    }
                }
            }
        }

        public SingerConfig[] getInstalledSingers() {
            return m_installed_singers.ToArray();
        }

        /// <summary>
        /// Gets the VsqID of program change.
        /// </summary>
        /// <param name="program_change"></param>
        /// <returns></returns>        
        public VsqID getSingerID( string singer ) {
            VsqID ret = new VsqID( 0 );
            ret.type = VsqIDType.Singer;
            SingerConfig sc = null;
            for ( int i = 0; i < m_singer_configs.Count; i++ ) {
                if ( m_singer_configs[i].VOICENAME == singer ) {
                    sc = m_singer_configs[i];
                    break;
                }
            }
            if ( sc == null ) {
                sc = new SingerConfig();
            }
            int lang = 0;
            foreach ( SingerConfig sc2 in m_installed_singers ) {
                if ( sc.VOICEIDSTR == sc2.VOICEIDSTR ) {
                    lang = (int)VocaloSysUtil.getLanguageFromName( sc.VOICENAME );
                    break;
                }
            }
            ret.IconHandle = new IconHandle();
            ret.IconHandle.IconID = "$0701" + sc.Program.ToString( "0000" );
            ret.IconHandle.IDS = sc.VOICENAME;
            ret.IconHandle.Index = 0;
            ret.IconHandle.Language = lang;
            ret.IconHandle.Length = 1;
            ret.IconHandle.Original = sc.Original;
            ret.IconHandle.Program = sc.Program;
            ret.IconHandle.Caption = "";
            return ret;
        }
        
        /// <summary>
        /// Gets the singer information of pecified program change.
        /// </summary>
        /// <param name="program_change"></param>
        /// <returns></returns>
        public SingerConfig getSingerInfo( string singer ) {
            foreach ( SingerConfig item in m_singer_configs ) {
                if ( item.VOICENAME == singer ) {
                    return item;
                }
            }
            return null;
        }

        /// <summary>
        /// Gets the list of singer configs.
        /// </summary>
        /// <returns></returns>
        public SingerConfig[] getSingerConfigs() {
            return m_singer_configs.ToArray();
        }
    }

}
