<#@ assembly name="System.Core"#>
<#@ assembly name="System.Data"#>
<#@ assembly name="$(ProjectDir)\T4\PublicDll\MySql.Data.dll" #>
<#@ import namespace="System" #>
<#@ import namespace="System.Data" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="MySql.Data.MySqlClient" #>
<#+
    public class EntityHelper
    {
        public static List<Entity> GetEntities(string connectionString, List<string> databases)
        {
            var list = new List<Entity>();
            var conn = new MySqlConnection(connectionString);
            try
            {
                conn.Open();
                var dbs = string.Join("','", databases.ToArray());
                var cmd = string.Format(@"SELECT `information_schema`.`COLUMNS`.`TABLE_SCHEMA`
                                                    ,`information_schema`.`TABLES`.`TABLE_NAME`
													,`information_schema`.`TABLES`.`TABLE_COMMENT`
                                                    ,`information_schema`.`COLUMNS`.`COLUMN_NAME`
                                                    ,`information_schema`.`COLUMNS`.`DATA_TYPE`
                                                    ,`information_schema`.`COLUMNS`.`COLUMN_COMMENT`
                                                    ,`information_schema`.`COLUMNS`.`IS_NULLABLE`
												    ,`information_schema`.`COLUMNS`.`COLUMN_KEY`
                                                FROM `information_schema`.`TABLES`
													LEFT JOIN `information_schema`.`COLUMNS`
														ON `information_schema`.`TABLES`.`TABLE_NAME`=`information_schema`.`COLUMNS`.`TABLE_NAME`
                                                WHERE `information_schema`.`COLUMNS`.`TABLE_SCHEMA` IN ('{0}') ", dbs);
                using (var reader = MySqlHelper.ExecuteReader(conn, cmd))
                {
                    while (reader.Read())
                    {
                        var db = reader["TABLE_SCHEMA"].ToString();
                        var tabcomment = reader["TABLE_COMMENT"].ToString();
                        var table = reader["TABLE_NAME"].ToString();
                        var column = reader["COLUMN_NAME"].ToString();
                        var type =  reader["DATA_TYPE"].ToString();
                        var comment = reader["COLUMN_COMMENT"].ToString();
                        var nullable = reader["IS_NULLABLE"].ToString();
                        var key = reader["COLUMN_KEY"].ToString();
                        var entity = list.FirstOrDefault(x => x.EntityName == table);
                        if(entity == null)
                        {
                            entity = new Entity(table,tabcomment);
                            entity.Fields.Add(new Field
                            {
                                Name = column,
                                Type =GetIsNullable( GetCLRType(type),nullable),
                                Comment = comment,
								Key = key
                            });
                            
                            list.Add(entity);
                        }
                        else
                        {
                            entity.Fields.Add(new Field
                            {
                                Name = column,
                                Type = GetIsNullable( GetCLRType(type),nullable),
                                Comment = comment,
								Key = key
                            });
                        }
                    }
                }
            }
            finally
            {
                conn.Close();
            }

            return list;
        }

        public static string GetCLRType(string dbType)
        {
            switch(dbType)
            {
                case "tinyint":
                case "smallint":
                case "mediumint":
                case "int":
                case "integer":
                    return "int";
                case "double":
                    return "double";
                case "float":
                    return "float";
                case "decimal":
                    return "decimal";
                case "numeric":
                case "real":
                    return "decimal";
                case "bit":
                    return "bool";
                case "date":
                case "time":
                case "year":
                case "datetime":
                case "timestamp":
                    return "DateTime";
                case "tinyblob":
                case "blob":
                case "mediumblob":
                case "longblog":
                case "binary":
                case "varbinary":
                    return "byte[]";
                case "char":
                case "varchar":                    
                case "tinytext":
                case "text":
                case "mediumtext":
                case "longtext":
                    return "string";
                case "point":
                case "linestring":
                case "polygon":
                case "geometry":
                case "multipoint":
                case "multilinestring":
                case "multipolygon":
                case "geometrycollection":
                case "enum":
                case "set":
                default:
                    return dbType;
            }
        }

        public static string GetIsNullable(string type,string nullable)
        {  
			if(nullable.ToLower()=="yes" && type.ToLower() != "string")
				return "Nullable<"+type+">";  
			return type;
        }
    }

    public class Entity
    {
        public Entity()
        {
            this.Fields = new List<Field>();
        }

        public Entity(string name,string comment)
            : this()
        {
            this.EntityName = name;
            this.EntityComment = comment;
        }

        public string EntityName { get;set; }
        public string EntityComment { get;set; }
        public List<Field> Fields { get;set; }
    }

    public class Field
    {
        public string Name { get;set; }
        public string Type { get;set; }
        public string Comment { get;set; }
        public string Key { get;set; }
    }
#>

