#if UNITY_EDITOR
using UnityEngine;
using System.Collections;
using UnityEditor;
using System.IO;
using System.Collections.Generic;
using System;
using Random = UnityEngine.Random;
using System.Globalization;

public class PostImportTool : AssetPostprocessor
{   
	class Section
    {
		public int Offset;
		public int NumIndices;
		public int Materialindex;
		public string MaterialName;
		public Material Mat;
	}
	class MeshBinding
    {
		public Mesh mesh;
		public MeshRenderer renderer;
    }	
	void GetFloatsFromLine( string Line, ref List<float> Floats, GameObject gameobject )
	{
		Floats.Clear();

		string[] Tokens = Line.Split(new char[]{ ' ' } );
		
		for( int u = 1; u < Tokens.Length; u++ )
		{
			try
			{
				CultureInfo ci = (CultureInfo)CultureInfo.InvariantCulture.Clone();
				ci.NumberFormat.CurrencyDecimalSeparator = ".";
				float Val = float.Parse( Tokens[u], ci.NumberFormat);
				Floats.Add( Val );
			}
			catch( FormatException e )
			{
				Debug.LogError( "float.Parse failed in " + gameobject.name + " input=" + Tokens[u] + " exception=" + e.Message );
			}
		}
	}
	void GetIntsFromLine( string Line, ref List<int> Ints, GameObject gameobject )
	{
		Ints.Clear();

		string[] Tokens = Line.Split(new char[]{ ' ', '/' } );

		for( int u = 1; u < Tokens.Length; u++ )
		{
			try
			{
				int Val = int.Parse( Tokens[u] );
				Ints.Add( Val );
			}
			catch( FormatException e )
			{
				Debug.LogError( "int.Parse failed in " + gameobject.name + " input=" + Tokens[u] + " exception=" + e.Message );
			}
		}
	}
	private void OnPostprocessModel(GameObject gameobject)   
	{
		UnityEditor.ModelImporter importer = this.assetImporter as UnityEditor.ModelImporter;

		string Path = importer.assetPath;
		if( !Path.Contains( ".obj" ) )
			return;


		string OBJFile = File.ReadAllText( Path );

		List<float> Floats = new List<float>();
		List<int> Ints = new List<int>();

		List<Vector3> Vertices = new List<Vector3>();
		List<Color> Colors = new List<Color>();
		List<Vector2> Texcoords0 = new List<Vector2>();
		List<Vector2> Texcoords1 = new List<Vector2>();
		List<Vector3> Normals = new List<Vector3>();
		List<Vector4> Tangents = new List<Vector4>();
		bool ReplaceNormals = true;
		List<int> Indices = new List<int>();
		List<Section> Sections = new List<Section>();
		string[] Lines = OBJFile.Split( new char[]{ '\n' } );
		for(int i=0; i<Lines.Length; i++ )
        {
			string Line = Lines[i];
			if (Line.StartsWith("v "))
            {
				string[] Tokens = Line.Split(new char[]{ ' ' } );
				Floats.Clear();
				for(int u=1; u<Tokens.Length; u++ )//0 should be "v"
                {
					try
					{
						CultureInfo ci = (CultureInfo)CultureInfo.InvariantCulture.Clone();
						ci.NumberFormat.CurrencyDecimalSeparator = ".";
						float Val = float.Parse( Tokens[u], ci.NumberFormat);
						Floats.Add( Val );
					}
					catch(FormatException e )
                    {
						Debug.LogError( "float.Parse failed for verts in " + gameobject.name + " input=" + Tokens[u] + " exception=" + e.Message );
					}
				}

				if ( Floats.Count >= 3)
					Vertices.Add( new Vector3( Floats[0], Floats[1], Floats[2] ) );
				else
					Vertices.Add( new Vector3( 0, 0, 0 ) );

				if ( Floats.Count == 7 )
                {
					Colors.Add( new Color( Floats[3], Floats[4], Floats[5], Floats[6] ) );
				}
			}
			else if( Line.StartsWith( "vt " ) )
			{
				GetFloatsFromLine( Line, ref Floats, gameobject );
				if( Floats.Count == 2 )
				{
					Texcoords0.Add( new Vector2( Floats[0], Floats[1] ) );
				}
				else
					Texcoords0.Add( new Vector2( 0, 0 ) );
			}
			else if( Line.StartsWith( "vt1 " ) )
			{
				GetFloatsFromLine( Line, ref Floats, gameobject );
				if( Floats.Count == 2 )
				{
					Texcoords1.Add( new Vector2( Floats[0], Floats[1] ) );
				}
				else
					Texcoords1.Add( new Vector2( 0, 0 ) );
			}
			else if( ReplaceNormals && Line.StartsWith( "vn " ) )
			{
				GetFloatsFromLine( Line, ref Floats, gameobject );
				if( Floats.Count == 3 )
				{
					Normals.Add( new Vector3( Floats[0], Floats[1], Floats[2] ) );
				}
				else
					Normals.Add( new Vector3( 0, 0, 0 ) );
			}
			else if( Line.StartsWith( "tan " ) )
			{
				GetFloatsFromLine( Line, ref Floats, gameobject );
				if( Floats.Count == 4 )
				{
					Tangents.Add( new Vector4( Floats[0], Floats[1], Floats[2], Floats[3] ) );
				}
				else
					Normals.Add( new Vector4( 0, 0, 0, 0 ) );
			}
			else if( Line.StartsWith( "f " ) )
			{
				GetIntsFromLine( Line, ref Ints, gameobject );
				if( Ints.Count == 9 )
				{
					Indices.Add( Ints[0] - 1 );
					Indices.Add( Ints[3] - 1 );
					Indices.Add( Ints[6] - 1 );
				}
			}
			//"#Section %d Offset %d NumIndices %d MaterialIndex %d %s\n"
			if( Line.StartsWith( "#Section " ) )
			{
				string[] Tokens = Line.Split(new char[]{ ' ' } );
				if( Tokens.Length == 9 )
				{
					Section NewSection = new Section();
					NewSection.Offset = int.Parse( Tokens[3] );
					NewSection.NumIndices = int.Parse( Tokens[5] );
					//NewSection.Materialindex = int.Parse( Tokens[7] );
					NewSection.MaterialName = Tokens[8].Trim();
					Sections.Add( NewSection );
				}
			}
		}

		MeshBinding[] MeshArray = GetMeshes( gameobject);
		if( MeshArray.Length == 0 )
			return;

		MeshBinding Binding = MeshArray[0];
		Mesh m = Binding.mesh;

		if( m.vertices.Length != Vertices.Count )
		{
			Debug.LogError( "m.vertices.Length != Vertices.Count for " + gameobject.name );
		}
		if ( m.GetIndices( 0 ).Length != Indices.Count )
        {
			Debug.LogError( "m.GetIndices( 0 ).Length != Indices.Count for " + gameobject.name );
		}
		m.SetIndices( Indices.ToArray(), MeshTopology.Triangles, 0 );
		m.vertices = Vertices.ToArray();
		if( Texcoords0.Count != m.uv.Length )
		{
			Debug.LogError( "Texcoords0.Count != m.uv.Length for " + gameobject.name );
		}
		m.uv = Texcoords0.ToArray();

		if( Colors.Count > 0 )
		{
			if( m.vertices.Length != Colors.Count )
			{
				Debug.LogError( " Mesh vertex count != color count for " + gameobject.name );
			}
			else
			{
				m.colors = Colors.ToArray();
			}
		}
		if ( Texcoords1.Count > 0 )
        {
			if( m.vertices.Length != Texcoords1.Count )
			{
				Debug.LogError( " Mesh vertex count != Texcoords1 count for " + gameobject.name );
			}
			else
			{
				m.uv2 = Texcoords1.ToArray();
			}
		}

		if( Sections.Count > 1 )
		{
			SetupSubmeshes( m, Sections.ToArray(), gameobject.name );
		}

		Material[] UsedMaterials = GetSectionMaterials( Sections.ToArray() );
		Binding.renderer.sharedMaterials = UsedMaterials;

		if( ReplaceNormals && Normals.Count > 0 )
		{
			if( m.vertices.Length != Normals.Count )
			{
				Debug.LogError( " Mesh vertex count != Texcoords1 count " + gameobject.name );
			}
			else
			{
				m.normals = Normals.ToArray();
			}
		}
		if( Tangents.Count > 0 )
		{
			if ( m.tangents.Length == 0 || m.tangents.Length == Tangents.Count )
			{
				m.tangents = Tangents.ToArray();
			}
			else
			{
				Debug.LogError( " Mesh vertex count != Tangents count " + gameobject.name );
			}
		}
		m.RecalculateBounds();
	}
	Material[] GetSectionMaterials( Section[] sections )
	{
		Material[] AllMaterials = UnityEngine.Resources.FindObjectsOfTypeAll<Material>();
		Material[] UsedMaterials = new Material[sections.Length];

		for( int i = 0; i < sections.Length; i++ )
		{
			Section s = sections[i];

			if( !s.MaterialName.Equals( "None" ) )
			{
				for( int m = 0; m < AllMaterials.Length; m++ )
				{
					if( AllMaterials[m].name.Equals( s.MaterialName ) )
					{
						s.Mat = AllMaterials[m];
						UsedMaterials[i] = s.Mat;
						break;
					}
				}
			}
		}

		return UsedMaterials;
	}
	void SetupSubmeshes( Mesh mesh, Section[] sections, String Name )
	{		
		int[] AllIndices = mesh.GetIndices( 0 );
		mesh.subMeshCount = sections.Length;

		for(int i = 0; i<sections.Length; i++ )
        {
			Section s = sections[i];		
			
			int[] SectionIndices = new int[ s.NumIndices ];

			for(int u=0; u< s.NumIndices; u++ )
            {
				if ( s.Offset + u < AllIndices.Length)
					SectionIndices[u] = AllIndices[ s.Offset + u ];
				else
                {
					Debug.LogError( "AllIndices is too small for " + Name );
					break;
				}
			}

			mesh.SetIndices( SectionIndices, MeshTopology.Triangles, i );
		}		
	}
	MeshBinding[] GetMeshes( GameObject gameObject )
	{
		List<MeshBinding> MeshArray = new List<MeshBinding>();
		MeshFilter[] MFArray = gameObject.GetComponentsInChildren<MeshFilter>();
		if( MFArray != null )
		{
			for( int i = 0; i < MFArray.Length; i++ )
			{
				MeshFilter MF = MFArray[i];
				Mesh m = MFArray[i].sharedMesh;

				MeshBinding NewMeshBinding = new MeshBinding();
				NewMeshBinding.mesh = m;
				NewMeshBinding.renderer = MF.gameObject.GetComponent<MeshRenderer>();
				MeshArray.Add( NewMeshBinding );
			}
		}

		return MeshArray.ToArray();
	}
	[MenuItem( "RE/PrintMesh" )]
	static void PrintMesh()
	{
		if( Selection.gameObjects.Length == 0 )
			return;
		GameObject go = Selection.gameObjects[0];

		MeshFilter MF = go.GetComponent<MeshFilter>();
		Mesh mesh = MF.sharedMesh;

		string Data = "";
		Data += "Vertices " + mesh.vertexCount + "\n";

		for( int i = 0; i < mesh.subMeshCount; i++ )
		{
			int[] Indices = mesh.GetTriangles( i );
			
			uint BaseVertex = mesh.GetBaseVertex( i );
			Data += "Section " + i + " Indices " + Indices.Length + " BaseVertex " + BaseVertex + "\n";
		}

		Vector3[] vertices = mesh.vertices;
		for( int i = 0; i < vertices.Length; i++ )
		{
			Data += "v " + vertices[i].x + " " + vertices[i].y + " " + vertices[i].z + "\n";
		}

		for( int i = 0; i < mesh.subMeshCount; i++ )
		{
			int[] Indices = mesh.GetTriangles( i );
			Data += "Section " + i + "\n";
			for( int u = 0; u < Indices.Length; u += 3 )
			{
				int I1 = Indices[ u ]    + 1;
				int I2 = Indices[ u + 1] + 1;
				int I3 = Indices[ u + 2] + 1;
				//Debug.Log( "f " + I1 + " " + I2 + " " + I3 );
				Data += "f " + I3 + " " + I2 + " " + I1 + "\n";
			}
		}

		File.WriteAllText( "C:/UnrealToUnity/Out.txt", Data );
	}
}
#endif