using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using VisimBox.Renderer;
using VisimBox.Renderer.RenderObjects;
using VisiMath.Geometry;
using VisiMath;

namespace VisimBuilder
{
    public partial class MaterialEditor : Form, VisimBox.Resources.IResourceConsumer
    {
        IRenderContext myIRC;
        IRenderWindow myWindow;
        ILight myLight;
        Mesh myBoxMesh;
        Mesh mySphereMesh;

        LightEditDlg MyLightEdit = new LightEditDlg();



        ColorByte origoAmb, origoDiff, origoSpec, origoEmiss;
        //bool hasAmb, hasSpec, hasEmiss;
        Texture origoTex;
        RenderMaterialType origoType;

        bool wasChanged = false;

        bool disableMaterialTypeCheck = false;

        public string SelectedMaterial
        {
            get
            {
                return _SelectedMaterial;
            }
        }

        string _selmat;
        string _SelectedMaterial
        {
            get
            {
                return _selmat;
            }
            set
            {
                if (_selmat != value)
                {
                    _selmat = value;
                    Boss.SelectedMaterial = _selmat;
                }
            }
        }

        MainBuilderForm Boss;

        Timer RenderTimer;

        public MaterialEditor(MainBuilderForm boss)
        {
            Boss = boss;

            InitializeComponent();

            colorEditingAmb.AlphaStateEnabled = false;
            colorEditingDiff.AlphaStateEnabled = true;
            colorEditingSpecular.AlphaStateEnabled = false;
            colorEditingEmissive.AlphaStateEnabled = false;

            colorEditingAmb.ColorChanged += new ColorEditing.ColorChangedCallback(colorEditingColorChanged);
            colorEditingDiff.ColorChanged += new ColorEditing.ColorChangedCallback(colorEditingColorChanged);
            colorEditingSpecular.ColorChanged += new ColorEditing.ColorChangedCallback(colorEditingColorChanged);
            colorEditingEmissive.ColorChanged += new ColorEditing.ColorChangedCallback(colorEditingColorChanged);

            spheretoolStripMenuItem1.Checked = true;
            boxToolStripMenuItem.Checked = false;

            myWindow = (VisimBox.Renderer.IRenderWindow)this.visimBoxRenderWindow;

            MyLightEdit.EnableDirectChange = true;
            MyLightEdit.lightEdit1.EnablePosAndDir = false;


            _selmat = boss.SelectedMaterial;
            UpdateMaterials();

            this.Disposed += new EventHandler(MaterialEditor_Disposed);
            //why can't I just ihehrit this? :( - because it's in designer code....

            RenderTimer = new Timer();
            RenderTimer.Interval = 500;
            RenderTimer.Tick += new EventHandler(RenderTimer_Tick);
        }

        void RenderTimer_Tick(object sender, EventArgs e)
        {
            RenderScreen();
        }

        void MaterialEditor_Disposed(object sender, EventArgs e)
        {
            if (myBoxMesh != null)
            {
                myBoxMesh.RemoveReference(this);
                myBoxMesh = null;
            }

            if (mySphereMesh != null)
            {
                mySphereMesh.RemoveReference(this);
                mySphereMesh = null;
            }
        }

        void colorEditingColorChanged(ColorEditing sender, ColorByte newcolor)
        {
            colorEditingColorChanged();
        }
        
        void colorEditingColorChanged()
        {
            if (checkBox1.Checked)
                colorEditingAmb.EditedColor = colorEditingDiff.EditedColor;
            if (checkBox2.Checked)
                colorEditingSpecular.EditedColor = colorEditingDiff.EditedColor;

            
            if (_SelectedMaterial == null)
                return;

            wasChanged = true;

            var matman = VisimBox.VisimEngine.Instance.Renderer.MaterialMan;

            IRenderMaterial mat = matman[_SelectedMaterial];

            switch (mat.MaterialType)
            {
                case RenderMaterialType.Simple:
                    mat.SetColorElement(MaterialElement.Diffuse, colorEditingDiff.EditedColor);
                    break;
                case RenderMaterialType.Textured:
                    mat.SetColorElement(MaterialElement.Diffuse, colorEditingDiff.EditedColor);
                    if (mat.HasColorElement(MaterialElement.Ambient))
                        mat.SetColorElement(MaterialElement.Ambient, colorEditingAmb.EditedColor);
                    if (mat.HasColorElement(MaterialElement.Specular))
                        mat.SetColorElement(MaterialElement.Specular, colorEditingSpecular.EditedColor);
                    if (mat.HasColorElement(MaterialElement.Emmissive))
                        mat.SetColorElement(MaterialElement.Emmissive, colorEditingEmissive.EditedColor);
                    break;
                case RenderMaterialType.Colored:
                    mat.SetColorElement(MaterialElement.Diffuse, colorEditingDiff.EditedColor);
                    if (mat.HasColorElement(MaterialElement.Ambient))
                        mat.SetColorElement(MaterialElement.Ambient, colorEditingAmb.EditedColor);
                    if (mat.HasColorElement(MaterialElement.Specular))
                        mat.SetColorElement(MaterialElement.Specular, colorEditingSpecular.EditedColor);
                    if (mat.HasColorElement(MaterialElement.Emmissive))
                        mat.SetColorElement(MaterialElement.Emmissive, colorEditingEmissive.EditedColor);
                    break;
                default:
                    break;
            }

            Invalidate();


        }


        protected void UpdateTextureCombo()
        {
            var texman = VisimBox.VisimEngine.Instance.Renderer.TextureMan;
            comboBoxTexSelect.Items.Clear();

            foreach (var tex in texman)
            {
                comboBoxTexSelect.Items.Add(tex.Value.Name);
            }
        }

        /// <summary>
        /// Update material list and settings from MaterialManager
        /// </summary>
        public void UpdateMaterials()
        {
            var matman = VisimBox.VisimEngine.Instance.Renderer.MaterialMan;


            UpdateTextureCombo();



            listBoxMaterials.Items.Clear();

            foreach (var mat in matman)
            {
                listBoxMaterials.Items.Add(mat.Key);
            }

            if (_SelectedMaterial != null)
            {
                int idx = listBoxMaterials.Items.IndexOf(_SelectedMaterial);
                listBoxMaterials.SelectedIndex = idx;
                if (idx < 0)
                {
                    _SelectedMaterial = null;
                }
            }
            SelectedChanged();
        }

        private void EnableAll(bool value = true)
        {
            radioButtonSpecial.Enabled = false;
            radioButtonSimple.Enabled = radioButtonTextured.Enabled =
                radioButtonTexturedSimple.Enabled = radioButtonColored.Enabled = value;
        }

        bool ignorenext = false;
        private void SelectedChanged()
        {
            if (ignorenext)
            {
                ignorenext = false;
                return;
            }
            if ((_SelectedMaterial != null) && (wasChanged))
            {
                if (ResolveChanges() == System.Windows.Forms.DialogResult.Cancel)
                {
                    listBoxMaterials.SelectedItem = _SelectedMaterial;
                    ignorenext = true;
                    return;
                }
            }
            
            _SelectedMaterial = (string)listBoxMaterials.SelectedItem;
            if (_SelectedMaterial == null)
            {
                EnableAll(false);
                return;
            }


            textBoxName.Text = _SelectedMaterial;

            EnableAll(true);
            
            
            var matman = VisimBox.VisimEngine.Instance.Renderer.MaterialMan;

            IRenderMaterial mat = matman[_SelectedMaterial];

            origoType = mat.MaterialType;

            disableMaterialTypeCheck = true;

            switch (mat.MaterialType)
            {
                case RenderMaterialType.Simple:
                    radioButtonSimple.Checked = true;
                    colorEditingDiff.Enabled = true;
                    colorEditingAmb.Enabled = colorEditingSpecular.Enabled = colorEditingEmissive.Enabled = false;
                    origoDiff = colorEditingDiff.EditedColor = mat.GetColorElement(MaterialElement.Diffuse);
                    comboBoxTexSelect.Enabled = false;
                    checkBox1.Enabled = checkBox2.Enabled = false;
                    break;
                case RenderMaterialType.SimpleTextured:
                    radioButtonTexturedSimple.Checked = true;
                    colorEditingAmb.Enabled = colorEditingSpecular.Enabled = colorEditingEmissive.Enabled = colorEditingDiff.Enabled = false;
                    comboBoxTexSelect.Enabled = true;
                    var tex = mat.GetTextureElement(MaterialElement.Diffuse);
                    if (tex != null)
                    {
                        comboBoxTexSelect.SelectedText = tex.Name;
                    }
                    else
                        comboBoxTexSelect.SelectedText = "";
                    checkBox1.Enabled = checkBox2.Enabled = false;
                    origoTex = tex;
                    break;
                case RenderMaterialType.Textured:
                    radioButtonTextured.Checked = true;
                    colorEditingDiff.Enabled = colorEditingAmb.Enabled = colorEditingSpecular.Enabled = colorEditingEmissive.Enabled = true;
                    origoDiff = colorEditingDiff.EditedColor = mat.GetColorElement(MaterialElement.Diffuse);
                    if (mat.HasColorElement(MaterialElement.Ambient))
                    {
                        origoAmb = colorEditingAmb.EditedColor = mat.GetColorElement(MaterialElement.Ambient);
                        //hasAmb = true;
                    }
                    else
                    {
                        colorEditingAmb.Enabled = false;
                        //hasAmb = false;
                    }
                    if (mat.HasColorElement(MaterialElement.Specular))
                    {
                        origoSpec = colorEditingSpecular.EditedColor = mat.GetColorElement(MaterialElement.Specular);
                        //hasSpec = true;
                    }
                    else
                    {
                        colorEditingSpecular.Enabled = false;
                        //hasSpec = false; 
                    }
                    if (mat.HasColorElement(MaterialElement.Emmissive))
                    {
                        origoEmiss = colorEditingEmissive.EditedColor = mat.GetColorElement(MaterialElement.Emmissive);
                        //hasEmiss = true;
                    }
                    else
                    {
                        //hasEmiss = false;
                        colorEditingEmissive.Enabled = false;
                    }
                    comboBoxTexSelect.Enabled = true;

                    var texx = mat.GetTextureElement(MaterialElement.Diffuse);
                    if (texx != null)
                    {
                        comboBoxTexSelect.SelectedText = texx.Name;
                    }
                    else
                        comboBoxTexSelect.SelectedText = "";
                    checkBox1.Enabled = checkBox2.Enabled = true;
                    origoTex = texx;
                    break;
                case RenderMaterialType.Colored:
                    radioButtonColored.Checked = true;
                    colorEditingDiff.Enabled = colorEditingAmb.Enabled = colorEditingSpecular.Enabled = colorEditingEmissive.Enabled = true;
                    colorEditingDiff.Enabled = colorEditingAmb.Enabled = colorEditingSpecular.Enabled = colorEditingEmissive.Enabled = true;
                    
                    
                    origoDiff = colorEditingDiff.EditedColor = mat.GetColorElement(MaterialElement.Diffuse);
                    if (mat.HasColorElement(MaterialElement.Ambient))
                    {
                        origoAmb = colorEditingAmb.EditedColor = mat.GetColorElement(MaterialElement.Ambient);
                        //hasAmb = true;
                    }
                    else
                    {
                        colorEditingAmb.Enabled = false;
                        //hasAmb = false;
                    }
                    if (mat.HasColorElement(MaterialElement.Specular))
                    {
                        origoSpec = colorEditingSpecular.EditedColor = mat.GetColorElement(MaterialElement.Specular);
                        //hasSpec = true;
                    }
                    else
                    {
                        colorEditingSpecular.Enabled = false;
                        //hasSpec = false; 
                    }
                    if (mat.HasColorElement(MaterialElement.Emmissive))
                    {
                        origoEmiss = colorEditingEmissive.EditedColor = mat.GetColorElement(MaterialElement.Emmissive);
                        //hasEmiss = true;
                    }
                    else
                    {
                        //hasEmiss = false;
                        colorEditingEmissive.Enabled = false;
                    }
                    comboBoxTexSelect.Enabled = false;
                    checkBox1.Enabled = checkBox2.Enabled = true;

                    break;
                default:
                    radioButtonColored.Enabled = radioButtonSimple.Enabled = radioButtonTextured.Enabled = radioButtonTexturedSimple.Enabled = false;
                    radioButtonSpecial.Checked = true;
                    colorEditingAmb.Enabled = colorEditingSpecular.Enabled = colorEditingEmissive.Enabled = colorEditingDiff.Enabled = false;
                    comboBoxTexSelect.Enabled = false;
                    checkBox1.Enabled = checkBox2.Enabled = false;
                    break;
            }

            disableMaterialTypeCheck = false;

            Invalidate();
        }


        private void TexChanged(object sender, EventArgs e)
        {
            if (_SelectedMaterial == null)
                return;

            var matman = VisimBox.VisimEngine.Instance.Renderer.MaterialMan;

            IRenderMaterial mat = matman[_SelectedMaterial];
            if ((mat.MaterialType != RenderMaterialType.SimpleTextured) && (mat.MaterialType != RenderMaterialType.Textured))
                return;

            var texman = VisimBox.VisimEngine.Instance.Renderer.TextureMan;

            string seltexture = (string)comboBoxTexSelect.SelectedItem;

            var tex = texman[seltexture];

            var ortex = mat.GetTextureElement(MaterialElement.Diffuse);

            if (ortex != tex)
            {
                mat.SetTextureElement(MaterialElement.Diffuse, tex);
                wasChanged = true;
            }

            Invalidate();

        }


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

        private void buttonLoadTexture_Click(object sender, EventArgs e)
        {
            if (openFileDialogTexture.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                string filen = VisimBox.FileSystem.Instance.GetRelativePath(openFileDialogTexture.FileName);
                Texture tex = VisimBox.VisimEngine.Instance.Renderer.TextureMan.Load(filen);
                if (tex == null)
                {
                    MessageBox.Show("Texture loading failed!");
                    return;
                }

                UpdateTextureCombo();
                comboBoxTexSelect.SelectedItem = filen;
            }            
        }


        #region startup, rendering, mouse control

        private void StartUp(object sender, EventArgs e)
        {
            var setts = new VisimBox.Renderer.RenderContextSettings(myWindow);
            setts.FullScreenSwitch = false;
            myIRC = VisimBox.VisimEngine.Instance.Renderer.AddNewContext(setts);
            if (myIRC == null)
            {
                MessageBox.Show("Material Editor - creating window for preview failed!");
            }


            if (myBoxMesh == null)
            {
                var meshman = VisimBox.VisimEngine.Instance.Renderer.MeshMan;

                if (meshman.Contains("MatEditCube"))
                {
                    myBoxMesh = meshman["MatEditCube"];
                }
                else
                {
                    var im = GeoFactory.CreateBox<TexturedVertex>(new Vector3(0), 5, 5, 5);

                    myBoxMesh = meshman.Add(im, "MatEditCube");
                }

                if (meshman.Contains("MatEditSphere"))
                {
                    mySphereMesh = meshman["MatEditSphere"];
                }
                else
                {
                    var im = GeoFactory.CreateSphere<TexturedVertex>(new Vector3(0), 4.5f, 0.3f);
                    mySphereMesh = meshman.Add(im, "MatEditSphere");
                }

                myBoxMesh.AddReference(this);
                mySphereMesh.AddReference(this);

            }

            lightnormal.Normalize();

            myLight = VisimBox.VisimEngine.Instance.Renderer.LightMan.AddDirectional("light", lightnormal, new ColorByte(20, 20, 20), ColorByte.White, ColorByte.White);


        }

        Matrix4 cubeMat = Matrix4.CreateTranslation(new Vector3(1, 0, 0));
        Quaternion cubeRotation = Quaternion.Identity;
        Vector3 translation = new Vector3(7.0f, 0, 0);
        Vector3 lightnormal = new Vector3(-1, 0, 1);

        private void RenderScreen(object sender, PaintEventArgs e)
        {
            RenderScreen();
        }

        private void RenderScreen()
        {
            if (myIRC == null)
                return;
            myIRC.StartFrame();

            myLight.Activate(0);

            cubeMat = Matrix4.CreateTransformation(ref cubeRotation, ref translation);
            myIRC.SetTransformation(ref cubeMat);


            if (_SelectedMaterial != null)
            {
                VisimBox.VisimEngine.Instance.Renderer.MaterialMan[_SelectedMaterial].Activate(new RendererEventArgs(myIRC.Renderer, myIRC, null));
            }


            if (spheretoolStripMenuItem1.Checked)
                mySphereMesh.Render(myIRC);
            else
                myBoxMesh.Render(myIRC);


            //myIRC.Start2DRender();

            //myIRC.DrawText(30, 30, "Dakalaka!");

            //myIRC.Stop2DRender();
            myIRC.EndFrame();
        }

        private void ShutDown(object sender, FormClosedEventArgs e)
        {
            VisimBox.VisimEngine.Instance.Renderer.RemoveContext(myIRC);
            myIRC = null;
        }


        float mouseX = 0, mouseY = 0;
        bool dragging = true;

        private void MyMouseDown(object sender, MouseEventArgs e)
        {
            mouseX = e.X;
            mouseY = e.Y;
            if ((e.Button == System.Windows.Forms.MouseButtons.Left) || (e.Button == System.Windows.Forms.MouseButtons.Right))
            {
                dragging = true;
            }
            else dragging = false;
            
            Invalidate();
        }

        private void MyMouseMove(object sender, MouseEventArgs e)
        {
            if (!dragging)
                return;
            
            float y = mouseY - e.Y;
            float z = mouseX - e.X;
            mouseX = e.X;
            mouseY = e.Y;

            Quaternion q = Quaternion.CreateFromRPY(0, y*0.01f, z*0.01f);

            if (e.Button == System.Windows.Forms.MouseButtons.Left)
            {
                cubeRotation = cubeRotation * q;
            }
            else
            {
                myLight.Direction = q * myLight.Direction;
                myLight.Direction.Normalize();
            }

            Invalidate();
        }

        private void MyMouseUp(object sender, MouseEventArgs e)
        {
            dragging = false;
            Invalidate();
        }

        #endregion


        private void LinkAmbient(object sender, EventArgs e)
        {
            if (checkBox1.Checked)
            {
                ColorByte amb = colorEditingAmb.EditedColor;
                ColorByte diff = colorEditingDiff.EditedColor;

                if (amb != diff)
                {
                    if (MessageBox.Show("Set Ambient to diffuse color?", "Linking colors", MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.No)
                    {
                        checkBox1.Checked = false;
                        return;
                    }
                    colorEditingAmb.EditedColor = diff;
                    colorEditingColorChanged(colorEditingAmb, diff);
                }
            }
        }

        private void LinkSpecular(object sender, EventArgs e)
        {
            if (checkBox2.Checked)
            {
                ColorByte spec = colorEditingSpecular.EditedColor;
                ColorByte diff = colorEditingDiff.EditedColor;

                if (spec != diff)
                {
                    if (MessageBox.Show("Set Specular to diffuse color?", "Linking colors", MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.No)
                    {
                        checkBox1.Checked = false;
                        return;
                    }
                    colorEditingSpecular.EditedColor = diff;
                    colorEditingColorChanged(colorEditingSpecular, diff);
                }
            }

        }

        private void SpherePick(object sender, EventArgs e)
        {
            spheretoolStripMenuItem1.Checked = true;
            boxToolStripMenuItem.Checked = false;
            Invalidate();
        }

        private void BoxPick(object sender, EventArgs e)
        {
            spheretoolStripMenuItem1.Checked = false;
            boxToolStripMenuItem.Checked = true;
            Invalidate();
        }

        private void SaveChanges()
        {

            origoAmb = colorEditingAmb.EditedColor;
            origoDiff = colorEditingDiff.EditedColor;
            origoEmiss = colorEditingEmissive.EditedColor;
            origoSpec = colorEditingSpecular.EditedColor;

            colorEditingColorChanged();


            wasChanged = false;

            origoTex = null;

            var matman = VisimBox.VisimEngine.Instance.Renderer.MaterialMan;

            IRenderMaterial mat = matman[_SelectedMaterial];
            if ((mat.MaterialType != RenderMaterialType.SimpleTextured) && (mat.MaterialType != RenderMaterialType.Textured))
                return;
            origoTex = mat.GetTextureElement(MaterialElement.Diffuse);
            Boss.RefreshMaterialList();
        }

        private void UndoChanges()
        {
            if (!wasChanged)
                return;

            colorEditingAmb.EditedColor = origoAmb;
            colorEditingSpecular.EditedColor = origoSpec;
            colorEditingDiff.EditedColor = origoSpec;
            colorEditingEmissive.EditedColor = origoEmiss;

            if (origoAmb != origoDiff)
                checkBox1.Checked = false;
            if (origoSpec != origoDiff)
                checkBox2.Checked = false;

            colorEditingColorChanged();

            var matman = VisimBox.VisimEngine.Instance.Renderer.MaterialMan;

            IRenderMaterial mat = matman[_SelectedMaterial];
            if ((mat.MaterialType != RenderMaterialType.SimpleTextured) && (mat.MaterialType != RenderMaterialType.Textured))
                return;
            mat.SetTextureElement(MaterialElement.Diffuse, origoTex);
            wasChanged = false;
        }

        RenderMaterialType GetTypeFromRadios()
        {
            if (radioButtonColored.Checked)
                return RenderMaterialType.Colored;
            if (radioButtonSimple.Checked)
                return RenderMaterialType.Simple;
            if (radioButtonTextured.Checked)
                return RenderMaterialType.Textured;
            if (radioButtonTexturedSimple.Checked)
                return RenderMaterialType.SimpleTextured;
            return RenderMaterialType.User;
        }

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

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

        private void CreateNew(object sender, EventArgs e)
        {
            if (wasChanged)
            {
                if (ResolveChanges() == System.Windows.Forms.DialogResult.Cancel)
                    return;
            }

            RenderMaterialType mattype = GetTypeFromRadios();
            if ((mattype == RenderMaterialType.Enhanced) || mattype == RenderMaterialType.User)
            {
                mattype = RenderMaterialType.Colored;
            }

            IRenderMaterial mat;
            
            var matman = VisimBox.VisimEngine.Instance.Renderer.MaterialMan;
            Texture tex = null;

            switch (mattype)
            {
                case RenderMaterialType.Simple:
                    mat = matman.Add("newmaterial", ColorByte.White);
                    break;
                case RenderMaterialType.Colored:
                    mat = matman.Add("newmaterial", StandardColorValues.Default());
                    break;
                case RenderMaterialType.Textured:
                    mat = matman.Add("newmaterial", tex, StandardColorValues.Default());
                    break;
                case RenderMaterialType.SimpleTextured:
                    mat = matman.Add("newmaterial", tex);
                    break;
                default:
                    MessageBox.Show("Unssupported type of material!");
                    return;
            }
            
            Boss.RefreshMaterialList();
            _SelectedMaterial = mat.Name;
            UpdateMaterials();
        }

        private void CreateCopy(object sender, EventArgs e)
        {
            if (SelectedMaterial == null)
            {
                MessageBox.Show("No material selected!");
                return;
            }

            if (wasChanged)
            {
                if (ResolveChanges() == System.Windows.Forms.DialogResult.Cancel)
                    return;
                //todo - offer user to save to a new copy
            }

            var matman = VisimBox.VisimEngine.Instance.Renderer.MaterialMan;
            
            IRenderMaterial mat = matman.CreateCopy(SelectedMaterial);

            Boss.RefreshMaterialList();
            _SelectedMaterial = mat.Name;

            UpdateMaterials();
        }

        private void FileClose(object sender, EventArgs e)
        {
            this.Close();
        }

        private void CheckReferences(object sender, EventArgs e)
        {
            if (_SelectedMaterial == null)
            {
                MessageBox.Show("No material selected");
                return;
            }

            var mat = VisimBox.VisimEngine.Instance.Renderer.MaterialMan[_SelectedMaterial];

            if (mat == null)
            {
                MessageBox.Show("Can't locate material!");
                return;
            }

            string message = string.Format("Material {0} is references {1} times ({2} of it are null references", _SelectedMaterial, 
                mat.References.ToString(), mat.NullReferences.ToString());
            MessageBox.Show(message);
            //todo : gather more info about consumers?
        }

        private void EditLight(object sender, EventArgs e)
        {
            MyLightEdit.AttachedLight = myLight;
            RenderTimer.Start();
            MyLightEdit.ShowDialog();
            RenderTimer.Stop();
            MyLightEdit.AttachedLight = null;
        }

        private void SaveLibrary(object sender, EventArgs e)
        {
            if (wasChanged)
            {
                if (ResolveChanges() == System.Windows.Forms.DialogResult.Cancel)
                    return;
            }

            openFileDialogMaterial.Title = "Save material library";
            openFileDialogMaterial.CheckFileExists = false;
            if (openFileDialogMaterial.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                string filen = openFileDialogMaterial.FileName;

                if (VisimBox.FileSystem.Instance.FileExists(filen))
                {
                    if (MessageBox.Show("File exists, overwrite?", "Material library saving", MessageBoxButtons.OKCancel) != System.Windows.Forms.DialogResult.OK)
                        return;
                }
                VisimBox.VisimEngine.Instance.Renderer.MaterialMan.SaveLibrary(filen);
            }
        }

        private void LoadLibrary(object sender, EventArgs e)
        {
            if (wasChanged)
            {
                if (ResolveChanges() == System.Windows.Forms.DialogResult.Cancel)
                    return;
            }

            openFileDialogMaterial.Title = "Load material library";
            openFileDialogMaterial.CheckFileExists = true;
            if (openFileDialogMaterial.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                string filen = openFileDialogMaterial.FileName;

                if (VisimBox.FileSystem.Instance.FileExists(filen))
                {
                    VisimBox.VisimEngine.Instance.Renderer.MaterialMan.LoadLibrary(filen);
                    Boss.RefreshMaterialList();
                    UpdateMaterials();
                }
                else MessageBox.Show("File doesn't exist!");
            }
            
        }
        

        private DialogResult ResolveChanges()
        {
            DialogResult res = MessageBox.Show("Values changed, save?", "Save changes?", MessageBoxButtons.YesNoCancel);

            if (res == System.Windows.Forms.DialogResult.Yes)
            {
                SaveChanges();
            }
            else
                if (res == System.Windows.Forms.DialogResult.No)
                {
                    UndoChanges();
                }
            return res;
        }

        private void TryToShutDown(object sender, FormClosingEventArgs e)
        {
            if (!wasChanged)
                return;

            if (ResolveChanges() == System.Windows.Forms.DialogResult.Cancel)
            {
                e.Cancel = true;
            }
        }


        #region IResourceConsumer Members

        public void ResourceDisposing(VisimBox.Resources.IResource resource)
        {
            throw new ArgumentException("MaterialEditor losing resource!"); //should never happen
        }

        public bool ResourceReplaced(VisimBox.Resources.IResource original, VisimBox.Resources.IResource newresource)
        {
            throw new ArgumentException("MaterialEditor losing resource!"); //should never happen
        }

        #endregion

        private void MaterialTypeSwitch(object sender, EventArgs e)
        {
            if (disableMaterialTypeCheck)
                return;

            if (_SelectedMaterial == null)
                return;
            


            RenderMaterialType rmat = GetTypeFromRadios();
            var matman = VisimBox.VisimEngine.Instance.Renderer.MaterialMan;

            IRenderMaterial mat = matman[_SelectedMaterial];

            if (mat.MaterialType == rmat)
                return;
            
            //ok, changing material type...

            if ((mat.MaterialType == RenderMaterialType.Enhanced) || (mat.MaterialType == RenderMaterialType.User))
            {
                MessageBox.Show("Cannot change special material type!");
                radioButtonSpecial.Checked = true;
                return;
            }

            if (MessageBox.Show("Changing material type is not undoable operation, are you sure?", "Changing material type", MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.No)
                return;

            if (mat.References > 1) //1 reference for material manager
            {
                if (MessageBox.Show("Material has references to it, are you sure you want to change it's type?",
                    "Material changing", MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.No)
                {
                    disableMaterialTypeCheck = true;
                    switch (mat.MaterialType)
                    {
                        case RenderMaterialType.Simple:
                            radioButtonSimple.Checked = true;
                            break;
                        case RenderMaterialType.SimpleTextured:
                            radioButtonTexturedSimple.Checked = true;
                            break;
                        case RenderMaterialType.Textured:
                            radioButtonTextured.Checked = true;
                            break;
                        case RenderMaterialType.Colored:
                            radioButtonColored.Checked = true;
                            break;
                        default:
                            radioButtonSpecial.Checked = true;    
                        break;
                    }
                    disableMaterialTypeCheck = false;
                    return;
                }
            }

            IRenderMaterial newmat;

            //create new material

            StandardColorValues val = new StandardColorValues();
            val.Ambient = colorEditingAmb.EditedColor;
            val.Diffuse = colorEditingDiff.EditedColor;
            val.Emissive = colorEditingEmissive.EditedColor;
            val.Specular = colorEditingSpecular.EditedColor;

            switch (rmat)
            {
                case RenderMaterialType.Simple:
                    newmat = matman.Add("replacemat", colorEditingDiff.EditedColor);
                    break;
                case RenderMaterialType.SimpleTextured:
                    newmat = matman.Add("replacemat", mat.GetTextureElement(MaterialElement.Diffuse));
                    break;
                case RenderMaterialType.Colored:
                    newmat = matman.Add("replacemat", val);
                    break;
                case RenderMaterialType.Textured:
                    newmat = matman.Add("replacemat", mat.GetTextureElement(MaterialElement.Diffuse), val);
                    break;
                default:
                    MessageBox.Show("Can't create new material of special type!");
                    return;
            }

            //update references via material manager

            matman.ReplaceMaterial(mat, newmat, true);
            wasChanged = false;
            UpdateMaterials();
        }

        private void NameKeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == (char)13)
                Rename();
        }

        private void NameFocusLeave(object sender, EventArgs e)
        {
            Rename();
        }

        private void Rename()
        {
            if (_SelectedMaterial == null)
                return;
            if (_SelectedMaterial == textBoxName.Text)
                return;

            if (MessageBox.Show("Rename " + _SelectedMaterial + " to " + textBoxName.Text + "?\nSome nodes might use only it's name and lose it after renaming!", "Material Renaming", MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.Yes)
            {
                VisimBox.VisimEngine.Instance.Renderer.MaterialMan.Rename(_SelectedMaterial, textBoxName.Text, true);
                _SelectedMaterial = textBoxName.Text;
                UpdateMaterials();
                
            }
            else
                textBoxName.Text = _SelectedMaterial;
        }
    }
}
