// reset all migration
// run all migration's down function
func Reset() error {
	sm := sortMap(migrationMap)
	i := 0
	for j := len(sm) - 1; j >= 0; j-- {
		v := sm[j]
		if isRollBack(v.name) {
			beego.Info("skip the", v.name)
			time.Sleep(1 * time.Second)
			continue
		}
		beego.Info("start reset:", v.name)
		v.m.Reset()
		v.m.Down()
		err := v.m.Exec(v.name, "down")
		if err != nil {
			beego.Error("execute error:", err)
			time.Sleep(2 * time.Second)
			return err
		}
		i++
		beego.Info("end reset:", v.name)
	}
	beego.Info("total success reset:", i, " migration")
	time.Sleep(2 * time.Second)
	return nil
}
//rollback the migration by the name
func Rollback(name string) error {
	if v, ok := migrationMap[name]; ok {
		beego.Info("start rollback")
		v.Reset()
		v.Down()
		err := v.Exec(name, "down")
		if err != nil {
			beego.Error("execute error:", err)
			time.Sleep(2 * time.Second)
			return err
		}
		beego.Info("end rollback")
		time.Sleep(2 * time.Second)
		return nil
	} else {
		beego.Error("not exist the migrationMap name:" + name)
		time.Sleep(2 * time.Second)
		return errors.New("not exist the migrationMap name:" + name)
	}
}
// execute the sql already add in the sql
func (m *Migration) Exec(name, status string) error {
	o := orm.NewOrm()
	for _, s := range m.sqls {
		beego.Info("exec sql:", s)
		r := o.Raw(s)
		_, err := r.Exec()
		if err != nil {
			return err
		}
	}
	return m.addOrUpdateRecord(name, status)
}
// upgrate the migration from lasttime
func Upgrade(lasttime int64) error {
	sm := sortMap(migrationMap)
	i := 0
	for _, v := range sm {
		if v.created > lasttime {
			beego.Info("start upgrade", v.name)
			v.m.Reset()
			v.m.Up()
			err := v.m.Exec(v.name, "up")
			if err != nil {
				beego.Error("execute error:", err)
				time.Sleep(2 * time.Second)
				return err
			}
			beego.Info("end upgrade:", v.name)
			i++
		}
	}
	beego.Info("total success upgrade:", i, " migration")
	time.Sleep(2 * time.Second)
	return nil
}
func isRollBack(name string) bool {
	o := orm.NewOrm()
	var maps []orm.Params
	num, err := o.Raw("select * from migrations where `name` = ? order by id_migration desc", name).Values(&maps)
	if err != nil {
		beego.Info("get name has error", err)
		return false
	}
	if num <= 0 {
		return false
	}
	if maps[0]["status"] == "rollback" {
		return true
	}
	return false
}