/*
 * Copyright 2010-2016 JetBrains s.r.o.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.jetbrains.kotlin.idea.test

import com.intellij.openapi.module.Module
import com.intellij.util.SmartFMap

interface TestFixtureExtension {
    fun setUp(module: Module)
    fun tearDown()

    companion object {
        @Volatile
        private var instances = SmartFMap.emptyMap<String, TestFixtureExtension>()

        @Suppress("UNCHECKED_CAST")
        fun loadFixture(className: String, module: Module): TestFixtureExtension {
            instances[className]?.let { return it }

            return (Class.forName(className).newInstance() as TestFixtureExtension).apply {
                this.setUp(module)
                instances = instances.plus(className, this)
            }
        }

        inline fun <reified T : TestFixtureExtension> loadFixture(module: Module) = loadFixture(T::class.qualifiedName!!, module) as T

        fun getFixture(className: String) = instances[className]

        inline fun <reified T : TestFixtureExtension> getFixture() = getFixture(T::class.qualifiedName!!) as? T

        fun unloadFixture(className: String) {
            instances[className]?.let {
                it.tearDown()
                instances = instances.minus(className)
            }
        }

        inline fun <reified T : TestFixtureExtension> unloadFixture() = unloadFixture(T::class.qualifiedName!!)
    }
}