/*
 * GenerateCharacter.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.ComponentModel;
using System.Drawing;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Windows.Forms;

using Boare.Lib.AppUtil;

namespace LipSync {

    public partial class GenerateCharacter : Form, IMultiLanguageControl {
        //Character3 m_table_group.Character;
        private TimeTableGroup m_table_group;
        private bool m_setTrans = false; // 透過色を設定している時に立つフラグ
        bool m_loading = true;
        string m_last_path = "";
        PictureBox m_dlg_picture;
        string m_selected_path;
        string m_last_image_folder = "";
        ExtensibleDialogs.OpenFileDialog m_heavy_dialog;
        bool m_abort_thread = false;

        public GenerateCharacter( TimeTableGroup table_group ) {
            InitializeComponent();
            ApplyLanguage();
            ApplyFont( AppManager.Config.Font.GetFont() );
            //m_table_group.Character = (Character3)character.Clone();
            m_table_group = (TimeTableGroup)table_group.Clone();
            this.menuFileOpen.Enabled = false;
            columnTag.Width = 50;
            columnTitle.Width = 130;
#if DEBUG
            menuEditDebugEditVersionInfo.Visible = true;
#endif
        }

        public GenerateCharacter( Character3 character ) {
            m_table_group = new TimeTableGroup( character.Name, 0, character );
            m_table_group.list.Clear();
            for ( int i = 0; i < character.Count; i++ ) {
                m_table_group.list.Add( new TimeTable( character[i].title, 0, TimeTableType.character, null ) );
            }
            InitializeComponent();
            ApplyLanguage();
            ApplyFont( AppManager.Config.Font.GetFont() );
            this.menuFileOpen.Enabled = true;
            columnTag.Width = 50;
            columnTitle.Width = 130;
#if DEBUG
            menuEditDebugEditVersionInfo.Visible = true;
#endif
        }

        public void ApplyLanguage() {
            this.lblTitle.Text = _( "Title" );
            this.lblTag.Text = _( "Tag" );
            this.columnTag.Text = _( "Tag" );
            this.columnTitle.Text = _( "Title" );
            this.btnUp.Text = _( "Up" );
            this.btnDown.Text = _( "Down" );
            this.btnAdd.Text = _( "Add" );
            this.btnOK.Text = _( "OK" );
            this.btnCancel.Text = _( "Cancel" );
            this.menuSetImage.Text = _( "Select image file" );
            this.menuTransparent.Text = _( "Select transparent color" );
            this.menuFile.Text = _( "File" ) + "(&F)";
            this.menuFileOpen.Text = _( "Open" ) + "(&O)";
            this.menuFileSave.Text = _( "Save" ) + "(&S)";
            this.label2.Text = _( "Character name" );
            this.Text = _( "Edit character" );
            this.menuEditTitle.Text = _( "Change title" );
            this.menuDelete.Text = _( "Delete" );
            this.groupBox1.Text = _( "Selected image" );

            this.menuFileImport.Text = _( "Import" ) + "(&I)";
            this.menuFileImportRsi.Text = _( "Open *.rsi" ) + "(&R)";

            this.menuFileExport.Text = _( "Export" ) + "(&E)";
            this.menuFileExportRsi.Text = _( "Save as *.rsi" ) + "(&R)";
            this.menuFileExportXml.Text = _( "Save as XML" ) + "(&X)";

            try {
                this.openLsc.Filter = _( "LipSync Character Config(*.lsc)|*.lsc" ) + "|" + _( "All Files(*.*)|*.*" );
            } catch {
                this.openLsc.Filter = "LipSync Character Config(*.lsc)|*.lsc|All Files(*.*)|*.*";
            }
            try {
                this.saveLsc.Filter = _( "LipSync Character Config(*.lsc)|*.lsc" ) + "|" + _( "All Files(*.*)|*.*" );
            } catch {
                this.saveLsc.Filter = "LipSync Character Config(*.lsc)|*.lsc|All Files(*.*)|*.*";
            }
            this.menuReset.Text = _( "Reset image" );
            try {
                this.openRsi.Filter = _( "RipSync Image(*.rsi)|*.rsi" ) + "|" + _( "All Files(*.*)|*.*" );
            } catch {
                this.openRsi.Filter = "RipSync Image(*.rsi)|*.rsi|All Files(*.*)|*.*";
            }
            try {
                this.saveRsi.Filter = _( "RipSync Image(*.rsi)|*.rsi" ) + "|" + _( "All Files(*.*)|*.*" );
            } catch {
                this.saveRsi.Filter = "RipSync Image(*.rsi)|*.rsi|All Files(*.*)|*.*" ;
            }
            this.menuEdit.Text = _( "Edit" ) + "(&E)";
            this.menuEditAdd.Text = _( "Add" );
            this.menuEditDelete.Text = _( "Delete" );
            this.menuEditDown.Text = _( "Down" );
            this.menuEditEditTitle.Text = _( "Change title" );
            this.menuEditReset.Text = _( "Reset image" );
            this.menuEditSetImage.Text = _( "Set image" );
            this.menuEditTransparent.Text = _( "Select transparent color" );
            this.menuEditUp.Text = _( "Up" );
        }

        public void ApplyFont( Font font ) {
            this.Font = font;
            foreach ( Control c in this.Controls ) {
                Boare.Lib.AppUtil.Misc.ApplyFontRecurse( c, font );
            }
        }

        public static string _( string s ) {
            return Messaging.GetMessage( s );
        }
        
        public TimeTableGroup EditedResult {
            get {
                return m_table_group;
            }
        }
        /*public Character3 EditedResult {
            get {
                return m_table_group.Character;
            }
        }*/

        public string LastPath {
            get {
                return m_last_path;
            }
            set {
                m_last_path = value;
            }
        }
        
        private void picturePreview_DoubleClick( object sender, EventArgs e ) {
            SetImage();
        }

        private void menuFileSave_Click( object sender, EventArgs e ) {
            try {
                saveLsc.Filter = _( "LipSync Character Config(*.lsc)|*.lsc" ) + "|" + _( "All Files(*.*)|*.*" );
            } catch {
                saveLsc.Filter = "LipSync Character Config(*.lsc)|*.lsc|All Files(*.*)|*.*";
            }
            if ( saveLsc.ShowDialog() == DialogResult.OK ) {
                m_last_path = saveLsc.FileName;
                using ( FileStream fs = new FileStream( saveLsc.FileName, FileMode.Create ) ) {
                    m_table_group.Character.Write( fs );
                }
            }
        }

        private void menuFileOpen_Click( object sender, EventArgs e ) {
            bool dialog_result = false;
            string f1 = _( "LipSync Character Config(*.lsc)|*.lsc" );
            string f2 = _( "LipSync Character Config(content.xml)|content.xml" );
            string f3 = _( "All Files(*.*)|*.*" );
            string filter = f1 + "|" + f2 + "|" + f3;
            string def_filter = "LipSync Character Config(*.lsc)|*.lsc|LipSync Character Config(content.xml)|content.xml|All Files(*.*)|*.*";
            //string path = "";
            if ( AppManager.Config.UseHeavyDialogInOpeningCharacterSettings ) {
                Panel p = new Panel();
                p.BorderStyle = BorderStyle.Fixed3D;
                m_dlg_picture = new PictureBox();
                p.Controls.Add( m_dlg_picture );
                m_dlg_picture.Dock = DockStyle.Fill;
                m_dlg_picture.SizeMode = PictureBoxSizeMode.Zoom;

                // filterの有効性をまずチェック
                try {
                    OpenFileDialog d = new OpenFileDialog();
                    d.Filter = filter;
                } catch {
                    filter = def_filter;
                }

                m_heavy_dialog = new ExtensibleDialogs.OpenFileDialog( p );
                m_heavy_dialog.DefaultExt = "lsc";
                m_heavy_dialog.FileName = m_last_path;
                m_heavy_dialog.Filter = filter;

                m_heavy_dialog.SelectionChanged += new ExtensibleDialogs.OpenFileDialog.SelectionChangedHandler( dlg_SelectionChanged );
                m_heavy_dialog.FolderChanged += new ExtensibleDialogs.OpenFileDialog.FolderChangedHandler( dlg_FolderChanged );
                m_abort_thread = false;
                bgWork.RunWorkerAsync( m_last_path );
                if ( m_heavy_dialog.ShowDialog() == DialogResult.OK ) {
                    dialog_result = true;
                } else {
                    dialog_result = false;
                }
                m_abort_thread = true;
            } else {
                try {
                    openLsc.Filter = filter;
                } catch {
                    openLsc.Filter = def_filter;
                }
                openLsc.FileName = m_last_path;
                if ( openLsc.ShowDialog() == DialogResult.OK ) {
                    dialog_result = true;
                } else {
                    dialog_result = false;
                }
                m_selected_path = openLsc.FileName;
            }
            if ( dialog_result ) {
                Bitmap preview;
                FileStream fs = null;
                try {
                    if ( Path.GetFileName( m_selected_path ).ToLower() == "content.xml" ) {
                        m_table_group.Character = Character3.FromXml( m_selected_path );
                    } else {
                        fs = new FileStream( m_selected_path, FileMode.Open );
                        BinaryFormatter bf = new BinaryFormatter();
                        m_table_group.Character = (Character3)bf.Deserialize( fs );
                        fs.Close();
                    }
                } catch ( Exception ex1 ) {
#if DEBUG
                    MessageBox.Show( "GenerateCharacter.menuFileOpen_Click; ex1=" + ex1.ToString() );
#endif
                    if ( fs != null ) {
                        fs.Close();
                    }
                    try {
                        LipSync.Character t = LipSync.Character.FromFile( m_selected_path );
                        m_table_group.Character = new Character3( t );
                    } catch ( Exception ex3 ) {
#if DEBUG
                            MessageBox.Show( "GenerateCharacter.menuFileOpen_Click; ex3=" + ex3.ToString() );
#endif
                        MessageBox.Show( _( "Failed file reading" ) );
                        return;
                    }
                }
                if ( m_table_group.Character != null ) {
                    picturePreview.Image = m_table_group.Character.DefaultFace;
                }
                update();
                m_last_path = m_selected_path;
            }
        }
        
        private void bgWork_DoWork( object sender, DoWorkEventArgs e ) {
#if DEBUG
            Common.DebugWriteLine( "bgWork_DoWork; start..." );
#endif
            string file = (string)e.Argument;
            if ( file == "" ) {
#if DEBUG
                Common.DebugWriteLine( "bgWork_DoWork; ...complete" );
#endif
                return;
            }
            string folder;
            if ( Directory.Exists( file ) ) {
                folder = file;
            } else {
                folder = Path.GetDirectoryName( file );
            }
            if ( !Directory.Exists( folder ) ) {
#if DEBUG
                Common.DebugWriteLine( "bgWork_DoWork; ...complete" );
#endif
                return;
            }
            string[] file_lsc = Directory.GetFiles( folder, "*.lsc", SearchOption.TopDirectoryOnly );
            string[] file_xml = Directory.GetFiles( folder, "content.xml", SearchOption.TopDirectoryOnly );
            List<string> files = new List<string>( file_lsc );
            files.AddRange( file_xml );
            //m_dictionaty.Clear();
            foreach ( string f in files ) {
                if ( m_abort_thread ) {
                    break;
                }
                CharacterConfigCollection.Register( f );
            }
            m_abort_thread = false;
#if DEBUG
            Common.DebugWriteLine( "bgWork_DoWork; ...complete" );
#endif
        }

        void dlg_FolderChanged( string path ) {
#if DEBUG
            Common.DebugWriteLine( "dlg_FolderChanged; path=" + path );
#endif
            if ( bgWork.IsBusy ) {
                m_abort_thread = true;
                while ( bgWork.IsBusy ) {
                    Application.DoEvents();
                }
            }
            m_abort_thread = false;
            bgWork.RunWorkerAsync( path );
        }

        void dlg_SelectionChanged( string path ) {
            if ( !File.Exists( path ) ) {
                return;
            }
            m_selected_path = path;
            string file = Path.GetFileName( path );
            StringFormat sf = new StringFormat();
            sf.Alignment = StringAlignment.Center;
            sf.LineAlignment = StringAlignment.Center;
            if ( CharacterConfigCollection.IsRegistered( path ) ) {
                Image img = CharacterConfigCollection.GetPreviewImage( path );
                if ( img != null ) {
                    m_dlg_picture.Image = img;
                } else {
                        m_dlg_picture.Image = new Bitmap( m_dlg_picture.Width, m_dlg_picture.Height );
                        using ( Graphics g = Graphics.FromImage( m_dlg_picture.Image ) ) {
                            g.DrawString(
                                "preview unavailable",
                                new Font( "Arial", 11 ),
                                Brushes.Black,
                                new RectangleF( 0, 0, m_dlg_picture.Width, m_dlg_picture.Height ),
                                sf );
                        }
                }
            } else {
                m_dlg_picture.Image = new Bitmap( m_dlg_picture.Width, m_dlg_picture.Height );
                using ( Graphics g = Graphics.FromImage( m_dlg_picture.Image ) ) {
                    g.DrawString(
                        "loading ...",
                        new Font( "Arial", 11 ),
                        Brushes.Black,
                        new RectangleF( 0, 0, m_dlg_picture.Width, m_dlg_picture.Height ),
                        sf );
                }
            }
        }
                
        /// <summary>
        /// 現在のm_table_group.Characterの内容を、listView1に適用します
        /// </summary>
        private void update() {
            if ( m_table_group.Character == null ) {
                return;
            }
            m_loading = true;
            textBox1.Text = m_table_group.Character.Name;
            string title = SelectedTitle;

            // 登録する．
            listView1.Items.Clear();
            for ( int i = 0; i < m_table_group.Character.Count; i++ ) {
                ListViewItem adding = new ListViewItem( new string[] { m_table_group.Character[i].title, m_table_group.Character[i].tag } );
                adding.Checked = m_table_group.Character[i].IsDefault;  // AddしてからCheckedを変更すると，イベントが発生してめんどい．
                listView1.Items.Add( adding );
            }
            if ( title != "" ) {
                for( int i = 0; i < listView1.Items.Count; i++ ){
                    if ( listView1.Items[i].Text == title ) {
                        listView1.Items[i].EnsureVisible();
                        break;
                    }
                }
            }
            this.Invalidate();
            m_loading = false;
        }

        private void btnOK_Click( object sender, EventArgs e ) {
            this.DialogResult = DialogResult.OK;
        }

        private void textBox1_TextChanged( object sender, EventArgs e ) {
            m_table_group.Character.Name = textBox1.Text;
        }

        private void btnAdd_Click( object sender, EventArgs e ) {
            Add();
        }

        private void menuSetImage_Click( object sender, EventArgs e ) {
            SetImage();
        }
        
        private void GenerateCharacter_DragDrop( object sender, DragEventArgs e ) {
#if DEBUG
            Common.DebugWriteLine( "GenerateCharacter_DragDrop" );
#endif
            if ( e.Data.GetDataPresent( DataFormats.FileDrop ) ) {
                object data = e.Data.GetData( DataFormats.FileDrop );
                if ( data is string[] ) {
                    string[] filename = (string[])data;
                    for ( int i = 0; i < filename.Length; i++ ) {
                        Image img = Common.ImageFromFile( filename[i] );
                        string title = Path.GetFileNameWithoutExtension( filename[i] );
#if DEBUG
                        Common.DebugWriteLine( "    filename[i]=" + filename[i] );
                        Common.DebugWriteLine( "    title=" + title );
#endif
                        if ( title != "" ) {
#if DEBUG
                            Common.DebugWriteLine( "    SetImage..." );
#endif
                            if ( m_table_group.Character[title] != null ) {
                                m_table_group.Character.SetImage( img, title );
                                picturePreview.Image = img;
                                int width = Math.Max( m_table_group.Character.Size.Width, img.Width );
                                int height = Math.Max( m_table_group.Character.Size.Height, img.Height );
#if DEBUG
                                Common.DebugWriteLine( "    Character3+Size..set()" );
#endif
                                m_table_group.Character.Size = new Size( width, height );
                            } else {
                                m_table_group.Character.Add( new ImageEntry( title, null, "", false, m_table_group.Character.Count ) );
                                m_table_group.Character.SetImage( img, title );
                                m_table_group.list.Add( new TimeTable( title, 0, TimeTableType.character, null ) );
                                int width = Math.Max( m_table_group.Character.Size.Width, img.Width );
                                int height = Math.Max( m_table_group.Character.Size.Height, img.Height );
                                m_table_group.Character.Size = new Size( width, height );
                                listView1.Items.Add( new ListViewItem( new string[] { title, "" } ) );
                                listView1.Items[listView1.Items.Count - 1].Selected = true;
                            }
                        }
                    }
                    this.Invalidate();
                }
            }
        }

        private void GenerateCharacter_DragEnter( object sender, DragEventArgs e ) {
            e.Effect = DragDropEffects.All;
        }
        
        private void menuTransparent_Click( object sender, EventArgs e ) {
            Transparent();
        }

        /// <summary>
        /// listView1にて現在選択されているアイテムの名前を取得します
        /// </summary>
        private string SelectedTitle {
            get {
                for( int i = 0; i < listView1.Items.Count; i++ ) {
                    if( listView1.Items[i].Selected ) {
                        return listView1.Items[i].Text;
                    }
                }
                return "";
            }
        }

        private void pictureBox1_MouseClick( object sender, MouseEventArgs e ) {
            if ( m_setTrans ) {
                int x = e.X;
                int y = e.Y;
                string title = SelectedTitle;
                Image img = null;
                for ( int i = 0; i < m_table_group.Character.Count; i++ ) {
                    if ( m_table_group.Character[i].title == title ) {
                        m_table_group.Character[i].GetImage( m_table_group.Character.Size );
                    }
                }
                if ( img != null ) {
                    if ( x <= img.Width && y <= img.Height ) {
                        Bitmap bmp = new Bitmap( img );
                        Color tmp = bmp.GetPixel( x, y );
                        bmp.MakeTransparent( tmp );
                        m_table_group.Character.SetImage( bmp, title );
                        if ( picturePreview.Image != null ) {
                            picturePreview.Image.Dispose();
                        }
                        picturePreview.Image = (Image)bmp.Clone();
                        bmp.Dispose();
                        update();
                        picturePreview.Invalidate();
                    }
                }
                picturePreview.Cursor = Cursors.Arrow;
                m_setTrans = false;
            }
        }

        private void txtTag_TextChanged( object sender, EventArgs e ) {
            if ( txtTag.Enabled ) {
                string title = SelectedTitle;
                ImageEntry t = m_table_group.Character[title];
                if ( t != null ) {
                    t.tag = txtTag.Text;
                    for ( int i = 0; i < listView1.Items.Count; i++ ) {
                        if ( listView1.Items[i].Text == m_table_group.Character[title].title ) {
                            listView1.Items[i].SubItems[1].Text = txtTag.Text;
                            return;
                        }
                    }
                }
            }
        }
        
        private void menuEditTitle_Click( object sender, EventArgs e ) {
            Title();
        }

        private void menuDelete_Click( object sender, EventArgs e ) {
            Delete();
        }

        private void listView1_SelectedIndexChanged( object sender, EventArgs e ) {
            string title = SelectedTitle;
            if ( title == "" ) {
                List<int> draw = new List<int>();
                foreach ( ListViewItem item in listView1.Items ) {
                    if ( item.Checked ) {
                        ImageEntry ie = m_table_group.Character[item.Text];
                        if ( ie != null ) {
                            draw.Add( ie.Z );
                        }
                    }
                }
                picturePreview.Image = m_table_group.Character.Face( draw.ToArray() );
                return;
            }
            ImageEntry ie2 = m_table_group.Character[title];
            if ( ie2 != null ) {
                int index = ie2.Z;
                picturePreview.Image = m_table_group.Character.Face( new int[] { index } );
                lblThisTitle.Text = m_table_group.Character[title].title;
                txtTag.Enabled = false;
                txtTag.Text = m_table_group.Character[title].tag;
                if ( 0 <= index && index < 9 ) {
                    txtTag.Text += "(" + _( "NOT editable" ) + ")";
                    txtTag.Enabled = false;
                } else {
                    txtTag.Enabled = true;
                }
                this.Invalidate();
            }
        }

        private void mstripImage_Opening( object sender, CancelEventArgs e ) {
            string title = SelectedTitle;
            if ( title == "" ) {
                menuDelete.Enabled = false;
                menuEditTitle.Enabled = false;
                menuSetImage.Enabled = false;
                menuTransparent.Enabled = false;
            } else {
                int index = m_table_group.Character[title].Z;
                if ( 9 <= index ) {
                    menuDelete.Enabled = true;
                    menuEditTitle.Enabled = true;
                } else {
                    menuDelete.Enabled = false;
                    menuEditTitle.Enabled = false;
                }
                menuSetImage.Enabled = true;
                menuTransparent.Enabled = true;
            }
        }

        private void listView1_ItemChecked( object sender, ItemCheckedEventArgs e ) {
            if ( m_loading ) {
                return;
            }
            int changed_item = e.Item.Index;
            string title = listView1.Items[changed_item].Text;
#if DEBUG
            Common.DebugWriteLine( "listView1_ItemChecked; title=" + title );
#endif
            string tag = m_table_group.Character[title].tag;
            m_table_group.Character[title].IsDefault = e.Item.Checked;
            if ( tag != "" && e.Item.Checked ) {
                for ( int i = 0; i < listView1.Items.Count; i++ ) {
                    string temp_title = listView1.Items[i].Text;
                    string temp_tag = m_table_group.Character[temp_title].tag;
                    if ( temp_tag == tag && temp_title != title ) {
                        m_table_group.Character[temp_title].IsDefault = false;
                        listView1.Items[i].Checked = false;
                    }
                }
            }
            if ( SelectedTitle == "" ) {
                List<int> draw = new List<int>();
                foreach ( ListViewItem item in listView1.Items ) {
                    if ( item.Checked ) {
                        int index = m_table_group.Character[item.Text].Z;
                        if( index >= 0 ) {
                            draw.Add( index );
                        }
                    }
                }
                picturePreview.Image = m_table_group.Character.Face( draw.ToArray() );
            }
            this.Invalidate();
            //update();  //ここで呼ぶと、永久再帰呼び出しでStackOverFlowする
        }

        private void GenerateCharacter_Load( object sender, EventArgs e ) {
            update();
        }
        
        private void btnUp_Click( object sender, EventArgs e ) {
            Up();
        }

        private void btnDown_Click( object sender, EventArgs e ) {
            Down();
        }

        private void menuReset_Click( object sender, EventArgs e ) {
            Reset();
        }

        private void menuFileImportRsi_Click( object sender, EventArgs e ) {
            if( openRsi.ShowDialog() == DialogResult.OK ){
                CharacterEx character_ex = RsiReader.Read( openRsi.FileName );
                if ( character_ex.character != null ) {
                    m_table_group.Character = (Character3)character_ex.character.Clone();
                    update();
                }
            }
        }

        private void menuFileExportRsi_Click( object sender, EventArgs e ) {
            if ( saveRsi.ShowDialog() == DialogResult.OK ) {
                RsiWriter.Write( m_table_group.Character, saveRsi.FileName );
            }
        }

        private void bgWork_RunWorkerCompleted( object sender, RunWorkerCompletedEventArgs e ) {
            bgWork.CancelAsync();
        }

        private void menuEditSetImage_Click( object sender, EventArgs e ) {
            SetImage();
        }

        private void menuEditTransparent_Click( object sender, EventArgs e ) {
            Transparent();
        }

        #region Core of EditHandle
        private void Add() {
            using ( InputBox ib = new InputBox( _( "Title of image" ),
                                                _( "Input the title of image" ) ) ) {
                if ( ib.ShowDialog() == DialogResult.OK ) {
                    string new_title = ib.rText;
                    bool found = false;
                    foreach ( ImageEntry ie in m_table_group.Character ) {
                        if ( ie.title == new_title ) {
                            found = true;
                            break;
                        }
                    }
                    if ( !found ) {
                        m_table_group.Character.Add( new ImageEntry( ib.rText, null, "", false, m_table_group.Character.Count ) );
                        m_table_group.list.Add( new TimeTable( ib.rText, 0, TimeTableType.character, null ) );
                        listView1.Items.Add( new ListViewItem( new string[] { ib.rText, "" } ) );
                        listView1.Items[listView1.Items.Count - 1].Selected = true;
                    } else {
                        MessageBox.Show(
                            _( "This image title has been already registered" ),
                            _( "Error" ) );
                    }
                }
            }
            update();
        }

        private void Up() {
#if DEBUG
            Common.DebugWriteLine( "Up()" );
#endif
            string selected_title = SelectedTitle;
            int selected_index = -1;
            for ( int i = 0; i < listView1.Items.Count; i++ ) {
                if ( listView1.Items[i].Text == selected_title ) {
                    selected_index = i;
                    break;
                }
            }
            if ( selected_index >= 1 ) {
                string upper_title = listView1.Items[selected_index - 1].Text;
                ListViewItem b = (ListViewItem)listView1.Items[selected_index].Clone();
                listView1.Items[selected_index] = (ListViewItem)listView1.Items[selected_index - 1].Clone();
                listView1.Items[selected_index - 1] = b;
                listView1.Items[selected_index].Selected = false;
                listView1.Items[selected_index - 1].Selected = false;

                int upper_z = m_table_group.Character[upper_title].Z;
                int selected_z = m_table_group.Character[selected_title].Z;
#if DEBUG
                Common.DebugWriteLine( "    selected_title=" + selected_title );
                Common.DebugWriteLine( "    upper_title=" + upper_title );
#endif
                m_table_group.Character[selected_title].Z = upper_z;
                m_table_group.Character[upper_title].Z = selected_z;

                update();
                listView1.Items[selected_index - 1].Selected = true;
                listView1.Items[selected_index - 1].EnsureVisible();

                TimeTable ttable_upper = (TimeTable)m_table_group[selected_index - 1].Clone();
                m_table_group[selected_index - 1] = (TimeTable)m_table_group[selected_index].Clone();
                m_table_group[selected_index] = ttable_upper;
            }
#if DEBUG
            Common.DebugWriteLine( "-------------------------------" );
#endif
        }

        private void Down() {
#if DEBUG
            Common.DebugWriteLine( "Down()" );
#endif
            string selected_title = SelectedTitle;
            int selected_index = -1;
            for ( int i = 0; i < listView1.Items.Count; i++ ) {
                if ( listView1.Items[i].Text == selected_title ) {
                    selected_index = i;
                    break;
                }
            }
            if ( selected_index >= 0 && selected_index < listView1.Items.Count - 1 ) {
                string lower_title = listView1.Items[selected_index + 1].Text;
                ListViewItem b = (ListViewItem)listView1.Items[selected_index].Clone();
                listView1.Items[selected_index] = (ListViewItem)listView1.Items[selected_index + 1].Clone();
                listView1.Items[selected_index + 1] = b;
                listView1.Items[selected_index].Selected = false;
                listView1.Items[selected_index + 1].Selected = false;

                int lower_z = m_table_group.Character[lower_title].Z;
                int selected_z = m_table_group.Character[selected_title].Z;
#if DEBUG
                Common.DebugWriteLine( "    selected_title=" + selected_title );
                Common.DebugWriteLine( "    lower_title=" + lower_title );
#endif
                m_table_group.Character[lower_title].Z = selected_z;
                m_table_group.Character[selected_title].Z = lower_z;

                update();
                listView1.Items[selected_index + 1].Selected = true;
                listView1.Items[selected_index + 1].EnsureVisible();

                TimeTable ttable_lower = (TimeTable)m_table_group.list[selected_index + 1].Clone();
                m_table_group.list[selected_index + 1] = (TimeTable)m_table_group.list[selected_index].Clone();
                m_table_group.list[selected_index] = ttable_lower;
            }
#if DEBUG
            Common.DebugWriteLine( "-------------------------------" );
#endif
        }

        private void SetImage() {
            string title = SelectedTitle;
            if ( title != "" ) {
                openImage.FileName = "";
                if ( m_last_image_folder != "" ) {
                    openImage.InitialDirectory = m_last_image_folder;
                }
                if ( openImage.ShowDialog() == DialogResult.OK ) {
                    Image img = Common.ImageFromFile( openImage.FileName );
                    m_table_group.Character.SetImage( img, title );
                    picturePreview.Image = img;
                    if ( img != null ) {
                        int width = Math.Max( m_table_group.Character.Size.Width, img.Width );
                        int height = Math.Max( m_table_group.Character.Size.Height, img.Height );
                        m_table_group.Character.Size = new Size( width, height );
                    }
                    this.Invalidate();
                    m_last_image_folder = Path.GetDirectoryName( openImage.FileName );
                } else {
                    m_last_image_folder = openImage.InitialDirectory;
                }
            }
        }

        private void Transparent() {
            if ( SelectedTitle != "" ) {
                m_setTrans = true;
                picturePreview.Cursor = Cursors.Cross;
            }
        }

        private void Reset() {
            string title = SelectedTitle;
            if ( title != "" ) {
                m_table_group.Character[title].ResetImage();
                picturePreview.Image = null;
            }
        }
        
        private void Delete() {
            string title = SelectedTitle;
            if ( title == "" ) {
                return;
            }
            m_table_group.Character.Remove( title );
            for ( int i = 0; i < m_table_group.list.Count; i++ ) {
                if ( m_table_group.list[i].Text == title ) {
                    m_table_group.list.RemoveAt( i );
                    break;
                }
            }
            UpdateZOrder();
            picturePreview.Image = null;
            update();
        }

        /// <summary>
        /// m_table_group.listの順序を元に、m_table_group.Characterのzオーダーを新たに幡番する
        /// </summary>
        private void UpdateZOrder() {
            for ( int i = 0; i < m_table_group.list.Count; i++ ) {
                foreach ( ImageEntry ie in m_table_group.Character ) {
                    if ( ie.title == m_table_group.list[i].Text ) {
                        ie.Z = i;
                        break;
                    }
                }
            }
        }
        
        private void Title() {
            string title = SelectedTitle;
            if ( title == "" ) {
                return;
            }
            string edited_title = "";
            using ( InputBox ib = new InputBox(
                _( "Change title" ),
                _( "Input new title" ) ) ) {
                ib.rText = title;
                if ( ib.ShowDialog() == DialogResult.OK ) {
                    edited_title = ib.rText;
                    foreach ( ImageEntry ie in m_table_group.Character ) {
                        if ( title == ie.title ) {
                            ie.title = edited_title;
                            break;
                        }
                    }
                    for ( int i = 0; i < m_table_group.list.Count; i++ ) {
                        if ( title == m_table_group.list[i].Text ) {
                            m_table_group.list[i].Text = edited_title;
                            break;
                        }
                    }
                }
            }
            update();
        }
        #endregion

        private void menuEditDelete_Click( object sender, EventArgs e ) {
            Delete();
        }

        private void menuEditReset_Click( object sender, EventArgs e ) {
            Reset();
        }
        
        private void menuEditEditTitle_Click( object sender, EventArgs e ) {
            Title();
        }

        private void menuEditUp_Click( object sender, EventArgs e ) {
            Up();
        }

        private void menuEditDown_Click( object sender, EventArgs e ) {
            Down();
        }

        private void menuEditAdd_Click( object sender, EventArgs e ) {
            Add();
        }

        private void menuEditDebugEditVersionInfo_Click( object sender, EventArgs e ) {
#if DEBUG
            using ( InputBox ib = new InputBox( "", "input author" ) ) {
                if ( ib.ShowDialog() == DialogResult.OK ) {
                    m_table_group.Character.Author = ib.rText;
                }
            }
            using ( InputBox ib = new InputBox( "", "input version" ) ) {
                if ( ib.ShowDialog() == DialogResult.OK ) {
                    m_table_group.Character.Version = ib.rText;
                }
            }
#endif
        }

        private void menuFileExportXml_Click( object sender, EventArgs e ) {
            saveLsc.FileName = m_last_path;
            string f1 = _( "LipSync Character Config(content.xml)|content.xml" );
            string f2 = _( "All Files(*.*)|*.*" );
            string filter = f1 + "|" + f2;
            string def_filter = "LipSync Character Config(content.xml)|content.xml|All Files(*.*)|*.*";
            try {
                saveLsc.Filter = filter;
            } catch {
                saveLsc.Filter = def_filter;
            }
            if ( saveLsc.ShowDialog() == DialogResult.OK ) {
                this.m_table_group.Character.WriteXml( saveLsc.FileName );
                m_last_path = saveLsc.FileName;
            }
        }
    }

}
