text: package com.liyaos.forklift.slick
  
  import com.typesafe.config._
  import scala.concurrent.duration._
  import scala.concurrent.Future
  import scala.concurrent.Await
  import scala.concurrent.ExecutionContext.Implicits.global
  import slick.backend.DatabaseConfig
  import slick.jdbc.JdbcProfile
  import slick.jdbc.meta.MTable
  import com.liyaos.forklift.core.Migration
  import com.liyaos.forklift.core.MigrationManager
  
  trait SlickMigrationManager
      extends MigrationManager[Int, slick.dbio.DBIO[Unit]] {
    lazy val dbConfig = SlickMigrationsConfig.dbConfig
  
    import dbConfig.profile.api._
  
    class MigrationsTable(tag: Tag) extends Table[Int](tag, "__migrations__") {
      def id = column[Int]("id", O.PrimaryKey)
      def * = id
    }
  
    class DummyTable(tag: Tag, name: String) extends Table[Int](tag, name) {
      def id = column[Int]("id")
      def * = id
    }
  
    type SlickMigration = Migration[Int, DBIO[Unit]]
  
    lazy val db = dbConfig.db
  
    lazy val migrationsTable = TableQuery[MigrationsTable]
    override def init = {
      val f = db.run(migrationsTable.schema.create)
      Await.result(f, Duration.Inf)
    }
    override def alreadyAppliedIds = {
      val f = db.run(migrationsTable.map(_.id).result)
      Await.result(f, Duration.Inf)
    }
    def latest =
      if (alreadyAppliedIds.isEmpty) None
      else Some(alreadyAppliedIds.last)
  
    override protected def up(migrations: Iterator[SlickMigration]) = {
      val ups = DBIO.sequence(migrations flatMap { m =>
        List(m.up, migrationsTable += m.id)
      }).transactionally
      val f = db.run(ups)
      Await.result(f, Duration.Inf)
    }
  
    override def reset = {
      val drop = MTable.getTables(None, None, None, None).flatMap { s =>
        DBIO.sequence(s filter { t =>
          t.tableType != null && t.tableType.toLowerCase == "table"
        } map { t =>
          TableQuery(new DummyTable(_, t.name.name)).schema.drop
        })
      }
      val f = db.run(drop)
      Await.result(f, Duration.Inf)
    }
  }
  