/*
 * EnvSettings.cs
 * Copyright (c) 2007-2009 kbinani
 *
 * This file is part of LipSync.
 *
 * LipSync is free software; you can redistribute it and/or
 * modify it under the terms of the BSD License.
 *
 * LipSync 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.Drawing;
using System.IO;
using System.Windows.Forms;
using System.Xml.Serialization;

using Boare.Lib.AppUtil;

namespace LipSync {

    /// <summary>
    /// 操作環境の設定値を格納します
    /// </summary>
    public class EnvSettings : ICloneable{
        private static XmlSerializer m_xml_serializer = null;

        public float PixelPerSec = 150.0f;
        public float WheelRatio = 0.2f;
        public int TimeLineInterval = 5;
        public Rectangle WindowPosition = new Rectangle( 0, 0, 473, 435 );
        public bool WindowIsMaximized = false;
        public Rectangle PreviewWindowPos = new Rectangle( 0, 0, 349, 340 );
        public Rectangle CurveWindowPos = new Rectangle( 0, 0, 349, 340 );
        public bool PreviewMaximized = false;
        public bool CurveMaximized = false;
        public PictureBoxSizeMode PreviewZoomMode = PictureBoxSizeMode.Zoom;
        public string Language = "";
        public ColorSet TimeLineTitleColor = new ColorSet( Color.LightPink );
        public ColorSet TimeLineVsqColor = new ColorSet( Color.FromArgb( 175, 222, 82 ) );
        public ColorSet TimeLinePluginColor = new ColorSet( Color.FromArgb( 255, 184, 51 ) );
        public ColorSet TimeLineDefaultColor = new ColorSet( Color.LightBlue );
        public string PathFFmpeg = "";
        public string PathMEncoder = "";
        public bool PreviewHidden = false;
        public float LastPreviewAspecto = 0.5f;
        public FontConfig TelopDefaultFont = new FontConfig( "MS UI Gothic", 18 );
        public ColorSet TelopDefaultColor = new ColorSet( Color.Black );
        public bool PropertyHidden = false;
        public int LastPropertyWidth = 175;
        public int VerticalStringOffset = 3;
        public bool CloseMouthWhenSameVowelsRepeated = true;
        public bool GenerateCharacterAutomatically = true;
        public float EntryCombineThreshold = 0f;
        public string LastCharacterPath = "";
        public string LastMusicPath = "";
        public string LastVsqPath = "";
        public bool UseHeavyDialogInOpeningCharacterSettings = false;
        public bool DrawBars = true;
        /// <summary>
        /// Vsqトラックを常に表示するかどうかを表す
        /// </summary>
        public bool FixVsqTrackPosition = false;
        /// <summary>
        /// 最後に使用されたAviファイルへのパス
        /// </summary>
        public string LastAviPath = "";
        public FontConfig Font = new FontConfig( "MS UI Gothic", 9 );
        /// <summary>
        /// キャラクタ設定ファイルの編集時に、静止画ファイルの名前をそのまま画像のタイトルとするかどうか
        /// </summary>
        public bool FileNameAsImageTitle = true;

        private QuantizeMode m_quantize_mode = QuantizeMode.off;        // 音符編集時の量子化モード
        private bool m_quantize_triplet = false;                        // 3連符モードが有効かどうか
        private bool m_sync_at_centre = true;
        private int m_track_height = 15;
        private bool m_save_character_config_outside = false;
        private List<string> m_close_mouth_phonetic_symbols = new List<string>( new string[] { "b", "p", "m", "b'", "p'", "m'" } );
        private List<string> m_i_mouth_phonetic_symbols = new List<string>( new string[] { "k'", "g'", "S", "dZ", "tS", "J", "C" } );
        private List<string> m_u_mouth_phonetic_symbols = new List<string>( new string[] { @"p\", @"p\'", "w", "ts", "dz" } );
                
        public int TrackHeight {
            get {
                return m_track_height;
            }
            set {
                m_track_height = value;
                Size font_size = Misc.MeasureString( "abQBHqj", Font.GetFont() );
                VerticalStringOffset = (m_track_height - font_size.Height) / 2;
            }
        }

        public static EnvSettings FromFile( string config_file ) {
            EnvSettings env;
            if ( File.Exists( config_file ) ) {
                if ( m_xml_serializer == null ) {
                    m_xml_serializer = new XmlSerializer( typeof( EnvSettings ) );
                }
                FileStream fs = null;
                try {
                    fs = new FileStream( config_file, FileMode.Open );
                    env = (EnvSettings)m_xml_serializer.Deserialize( fs );
                } catch {
#if DEBUG
                    Common.DebugWriteLine( "EnvSettings2+FromFile" );
                    Common.DebugWriteLine( "   ctor from xml has been failed. trying ctor from EnvSettings." );
#endif
                    /*if ( fs != null ) {
                        fs.Close();
                    }
                    try {
                        fs = new FileStream( config_file, FileMode.Open );
                        BinaryFormatter bf = new BinaryFormatter();
                        EnvSettings env1 = (EnvSettings)bf.Deserialize( fs );
                        env = new EnvSettings2( env1 );
                    } catch ( Exception ex ){
#if DEBUG
                        Common.DebugWriteLine( "    ex=" + ex.ToString() );
#endif
                        env = new EnvSettings2();
                    } finally {
                        if ( fs != null ) {
                            fs.Close();
                        }
                    }*/
                    env = new EnvSettings();
                } finally {
                    if ( fs != null ) {
                        fs.Close();
                    }
                }
            } else {
                env = new EnvSettings();
                env.Save( config_file );
            }
            return env;
        }

        public EnvSettings() {
        }

        /*internal EnvSettings2( EnvSettings old ) {
            PixelPerSec = old.PIXEL_PER_SEC;
            WheelRatio = old.WHEEL_RATIO;
            TimeLineInterval = old.TIMELINE_INTERVAL;
            WindowPosition = old.WINDOW_POS;
            WindowIsMaximized = old.MAXIMIZED;
            PreviewWindowPos = old.PREVIEW_WINDOW_POS;
            CurveWindowPos = new Rectangle( 0, 0, 349, 340 );
            PreviewMaximized = false;
            CurveMaximized = false;
            PreviewZoomMode = old.PREVIEW_PICTUREMODE;
            if ( old.LANGUAGE == LipSync.Language.ja ) {
                Language = "ja";
            } else {
                Language = "";
            }
            TimeLineTitleColor = new ColorSet( old.TIMELINE_TITLE );
            TimeLineVsqColor = new ColorSet( old.TIMELINE_VSQ_ENTRY );
            TimeLinePluginColor = new ColorSet( old.TIMELINE_PLUGIN_ENTRY );
            TimeLineDefaultColor = new ColorSet( old.TIMELINE_DEFAULT_ENTRY );
            PathFFmpeg = old.PATH_FFMPEG;
            PathMEncoder = old.PATH_MENCODER;
            PreviewHidden = old.PREVIEW_HIDDEN;
            LastPreviewAspecto = old.LAST_ASPECTO;
            TelopDefaultFont = new FontConfig( old.TELOP_DEFAULT_FONT );
            TelopDefaultColor = new ColorSet( old.TELOP_DEFAULT_COLOR );
            PropertyHidden = old.PROPERTY_HIDDEN;
            LastPropertyWidth = old.LAST_PROPERTY_WIDTH;
            VerticalStringOffset = old.STRING_OFFSET;
            CloseMouthWhenSameVowelsRepeated = old.CLOSE_MOUTH_WHEN_SAME_VOWEL_REPEATED;
            GenerateCharacterAutomatically = old.GEN_CHARACTER_AUTOMATICELY;
            EntryCombineThreshold = old.COMBINE_THRESHOLD;
            LastCharacterPath = old.LAST_CHARACTER_PATH;
            LastMusicPath = old.LAST_MUSIC_PATH;
            LastVsqPath = old.LAST_VSQ_PATH;
            UseHeavyDialogInOpeningCharacterSettings = old.USE_HEAVY_DIALOG;
            DrawBars = true;
            FixVsqTrackPosition = false;
            LastAviPath = "";
            Font = new FontConfig( "MS UI Gothic", 9 );
            m_quantize_mode = QuantizeMode.off;
            m_quantize_triplet = false;
            m_sync_at_centre = true;
            m_track_height = old.TRACK_HEIGHT;
            m_save_character_config_outside = false;
            m_close_mouth_phonetic_symbols = old.LIST_NN;
            m_i_mouth_phonetic_symbols = old.LIST_I;
            m_u_mouth_phonetic_symbols = old.LIST_U;
        }*/

        public void Save( string file ) {
            if ( m_xml_serializer == null ) {
                m_xml_serializer = new XmlSerializer( typeof( EnvSettings ) );
            }
            using ( FileStream fs = new FileStream( file, FileMode.Create ) ) {
                m_xml_serializer.Serialize( fs, this );
            }
        }

        public bool SaveCharacterConfigOutside {
            get {
                return m_save_character_config_outside;
            }
        }
        
        [XmlArrayItem(typeof(string), ElementName="PhoneticSymbol")]
        public List<string> CloseMouthPhoneticSymbols {
            get {
                return m_close_mouth_phonetic_symbols;
            }
            set {
                m_close_mouth_phonetic_symbols = new List<string>( value.ToArray() );
            }
        }

        [XmlArrayItem( typeof( string ), ElementName = "PhoneticSymbol" )]
        public List<string> IMouthPhoneticSymbols {
            get {
                return m_i_mouth_phonetic_symbols;
            }
            set {
                m_i_mouth_phonetic_symbols = new List<string>( value.ToArray() );
            }
        }

        [XmlArrayItem( typeof( string ), ElementName = "PhoneticSymbol" )]
        public List<string> UMouthPhoneticSymbols {
            get {
                return m_u_mouth_phonetic_symbols;
            }
            set {
                m_u_mouth_phonetic_symbols = new List<string>( value.ToArray() );
            }
        }
        
        public QuantizeMode QuantizeMode {
            get {
                return m_quantize_mode;
            }
            set {
                m_quantize_mode = value;
            }
        }

        public bool QuantizeTripletEnabled {
            get {
                return m_quantize_triplet;
            }
            set {
                m_quantize_triplet = value;
            }
        }

        public void CleanUpMouthList() {
            for ( int i = 0; i < IMouthPhoneticSymbols.Count - 1; i++ ) {
                bool changed = true;
                while ( changed ) {
                    changed = false;
                    for ( int j = i + 1; j < IMouthPhoneticSymbols.Count; j++ ) {
                        if ( IMouthPhoneticSymbols[i] == IMouthPhoneticSymbols[j] ) {
                            IMouthPhoneticSymbols.RemoveAt( j );
                            changed = true;
                            break;
                        }
                    }
                }
            }
            for ( int i = 0; i < UMouthPhoneticSymbols.Count - 1; i++ ) {
                bool changed = true;
                while ( changed ) {
                    changed = false;
                    for ( int j = i + 1; j < UMouthPhoneticSymbols.Count; j++ ) {
                        if ( UMouthPhoneticSymbols[i] == UMouthPhoneticSymbols[j] ) {
                            UMouthPhoneticSymbols.RemoveAt( j );
                            changed = true;
                            break;
                        }
                    }
                }
            }
            for ( int i = 0; i < CloseMouthPhoneticSymbols.Count - 1; i++ ) {
                bool changed = true;
                while ( changed ) {
                    changed = false;
                    for ( int j = i + 1; j < CloseMouthPhoneticSymbols.Count; j++ ) {
                        if ( CloseMouthPhoneticSymbols[i] == CloseMouthPhoneticSymbols[j] ) {
                            CloseMouthPhoneticSymbols.RemoveAt( j );
                            changed = true;
                            break;
                        }
                    }
                }
            }
        }

        public bool SyncAtCentre {
            get {
                return m_sync_at_centre;
            }
            set {
                m_sync_at_centre = value;
            }
        }

        public object Clone() {
            EnvSettings res = new EnvSettings();
            res.CloseMouthWhenSameVowelsRepeated = this.CloseMouthWhenSameVowelsRepeated;
            res.EntryCombineThreshold = this.EntryCombineThreshold;
            res.GenerateCharacterAutomatically = this.GenerateCharacterAutomatically;
            res.Language = this.Language;
            res.LastPreviewAspecto = this.LastPreviewAspecto;
            res.LastCharacterPath = this.LastCharacterPath;
            res.LastMusicPath = this.LastMusicPath;
            res.LastPropertyWidth = this.LastPropertyWidth;
            res.LastVsqPath = this.LastVsqPath;
            res.IMouthPhoneticSymbols = new List<string>( this.IMouthPhoneticSymbols.ToArray() );
            res.CloseMouthPhoneticSymbols = new List<string>( this.CloseMouthPhoneticSymbols.ToArray() );
            res.UMouthPhoneticSymbols = new List<string>( this.UMouthPhoneticSymbols.ToArray() );
            res.WindowIsMaximized = this.WindowIsMaximized;
            res.PathFFmpeg = this.PathFFmpeg;
            res.PathMEncoder = this.PathMEncoder;
            res.PixelPerSec = this.PixelPerSec;
            res.PreviewZoomMode = this.PreviewZoomMode;
            res.PropertyHidden = this.PropertyHidden;
            res.Font = (FontConfig)this.Font.Clone();
            res.VerticalStringOffset = this.VerticalStringOffset;
            res.TelopDefaultColor = this.TelopDefaultColor;
            res.TelopDefaultFont = this.TelopDefaultFont;
            res.TimeLineDefaultColor = this.TimeLineDefaultColor;
            res.TimeLineInterval = this.TimeLineInterval;
            res.TimeLinePluginColor = this.TimeLinePluginColor;
            res.TimeLineTitleColor = this.TimeLineTitleColor;
            res.TimeLineVsqColor = this.TimeLineVsqColor;
            res.TrackHeight = this.TrackHeight;
            res.UseHeavyDialogInOpeningCharacterSettings = this.UseHeavyDialogInOpeningCharacterSettings;
            res.WheelRatio = this.WheelRatio;
            res.WindowPosition = this.WindowPosition;
            res.DrawBars = this.DrawBars;
            res.m_quantize_mode = this.m_quantize_mode;
            res.m_quantize_triplet = this.m_quantize_triplet;
            res.m_sync_at_centre = this.m_sync_at_centre;
            return res;
        }
    }

}
