/*
 * RsiReader.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.Web;
using System.Xml;

namespace LipSync {

    /// <summary>
    /// RipSyncのキャラクタ設定ファイル*.rsiを読込むためのクラス
    /// </summary>
    public class RsiReader {
        public static CharacterEx Read( string filepath ) {
            CharacterEx result = new CharacterEx();
            filepath = HttpUtility.UrlDecode( filepath );
            XmlDocument doc = new XmlDocument();
            doc.Load( filepath );
            string base_path = Path.GetDirectoryName( filepath );
            List<string> exclusion = new List<string>();

            foreach ( XmlNode level0 in doc.DocumentElement.ChildNodes ) {
                switch ( level0.LocalName ) {
                    case "Title":
                        result.character.Name = level0.InnerText;
                        break;
                    case "Size":
                        string t_string = level0.InnerText;
                        string[] spl = t_string.Split( ",".ToCharArray() );
                        int width = int.Parse( spl[0] );
                        int height = int.Parse( spl[1] );
                        result.character.Size = new Size( width, height );
                        break;
                    case "Triggers":
                        // 排他設定だけ読み取る
                        foreach ( XmlNode level1 in level0.ChildNodes ) {
                            if ( level1.LocalName == "Selection" ) {
                                foreach ( XmlNode level2 in level1.ChildNodes ) {
                                    if ( level2.LocalName == "Item" ) {
                                        foreach ( XmlAttribute attr in level2.Attributes ) {
                                            if ( attr.LocalName == "Trigger" ) {
                                                result.exclusion.Add( attr.InnerText );
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        break;
                }
            }

            foreach ( XmlNode level0 in doc.DocumentElement.ChildNodes ) {
                if ( level0.LocalName == "Images" ) {
                    foreach ( XmlNode level1 in level0.ChildNodes ) {
                        switch ( level1.LocalName ) {
                            case "Image":
                                string image_path = "";
                                string name = "";
                                string trigger = "";
                                Point center = new Point( 0, 0 );
                                foreach ( XmlAttribute attr in level1.Attributes ) {
                                    switch ( attr.LocalName ) {
                                        case "name":
                                            name = attr.InnerText;
                                            break;
                                        case "path":
                                            image_path = Path.Combine( base_path, attr.InnerText );
                                            break;
                                        case "trigger":
                                            trigger = attr.InnerText;
                                            break;
                                        case "center":
                                            string tmp = attr.InnerText;
                                            tmp = tmp.Replace( " ", "" );
                                            tmp = tmp.Trim();
                                            string[] spl = tmp.Split( ",".ToCharArray() );
                                            center = new Point( -int.Parse( spl[0] ), -int.Parse( spl[1] ) );
                                            break;
                                    }
                                }
                                Image img = null;
                                if ( File.Exists( image_path ) ) {
                                    img = Common.ImageFromFile( image_path );
                                }
                                bool found = false;
#if DEBUG
                                Common.DebugWriteLine( "RsiReader.Read(String); name=" + name );
                                Common.DebugWriteLine( "RsiReader.Read(String); center=" + center );
#endif
                                for ( int i = 0; i < result.character.Count; i++ ) {
                                    if ( result.character[i].title == name ) {
                                        found = true;
                                        if ( img != null ) {
                                            if ( center.X == 0 && center.Y == 0 ) {
                                                result.character.SetImage( img, name );
                                            } else {
                                                int width = result.character.Size.Width;
                                                int height = result.character.Size.Height;
                                                using ( Bitmap bmp = new Bitmap( width, height, System.Drawing.Imaging.PixelFormat.Format32bppArgb ) )
                                                using ( Graphics g = Graphics.FromImage( bmp ) ) {
                                                    g.DrawImage( img, center.X, center.Y, img.Width, img.Height );
#if DEBUG
                                                    string temp = @"C:\" + name + ".png";
                                                    Common.DebugWriteLine( "temp=" + temp );
                                                    bmp.Save( temp, System.Drawing.Imaging.ImageFormat.Png );
#endif
                                                    result.character.SetImage( bmp, name );
                                                }
                                            }
                                        } else {
                                            result.character.SetImage( null, name );
                                        }
                                    }
                                }
                                if ( !found ) {
                                    result.character.Add( new ImageEntry( name, null, "", false ) );
                                    if ( center.X == 0 && center.Y == 0 ) {
                                        result.character.SetImage( img, name );
                                    } else {
                                        int width = result.character.Size.Width;
                                        int height = result.character.Size.Height;
                                        using ( Bitmap bmp = new Bitmap( width, height, System.Drawing.Imaging.PixelFormat.Format32bppArgb ) )
                                        using ( Graphics g = Graphics.FromImage( bmp ) ) {
                                            g.DrawImage( img, center.X, center.Y, img.Width, img.Height );
#if DEBUG
                                            string temp = @"C:\" + name + ".png";
                                            Common.DebugWriteLine( "temp=" + temp );
                                            bmp.Save( temp, System.Drawing.Imaging.ImageFormat.Png );
#endif
                                            result.character.SetImage( bmp, name );
                                        }
                                    }
                                }
                                break;
                        }

                    }
                }
            }
#if DEBUG
            Common.DebugWriteLine( "RsiReader.Read(String); result.character.Size=" + result.character.Size );
#endif
            return result;
        }

    }

}
