package gaf3.core.services.menu.service.impl

import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.databind.SerializationFeature
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule
import gaf3.core.exception.BusinessError
import gaf3.core.services.menu.GafMenuConfigure
import gaf3.core.services.menu.domain.MenuItem
import gaf3.core.services.menu.service.GafMenuStore
import org.apache.commons.io.IOUtils
import org.slf4j.LoggerFactory
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
import org.springframework.stereotype.Service
import java.io.FileNotFoundException
import java.nio.charset.Charset

@Service
@ConditionalOnProperty(prefix = "gaf.menu", name = ["store-type"], havingValue = "file", matchIfMissing = true)
class FileMenuStore(val config: GafMenuConfigure): GafMenuStore {
    override fun load(): List<MenuItem> {
        try {
            val jsonData = IOUtils.toString(config.itemsFile.inputStream, Charset.forName("UTF-8"))
            // TODO: dyg@20200608, fastjson 1.2.69~1.2.70此处有问题，无法解析children数据
            // val items = JSON.parseArray(jsonData, MenuItem::class.java)
            val items = parseObject(jsonData, Array<MenuItem>::class.java)
            transItems(items)
            return items.toList()
        }catch (ex: FileNotFoundException){
            log.error(ex.message)
            if(log.isDebugEnabled) {
                ex.printStackTrace()
            }
            throw BusinessError(BusinessError.ERR_SERVICE_FAULT, "菜单文件不存在")
        }
    }

    override fun save(data: MenuItem): MenuItem {
        throw NotImplementedError()
    }

    override fun delete(id: String) {
        throw NotImplementedError()
    }

    fun transItems(items: List<MenuItem>, pid: String? = null) {
        items.forEachIndexed { index, item ->
            item.pid = pid ?: "0"
            item.id = item.id ?: (pid?.let { "$pid-${index+1}" } ?: "${index+1}")
            item.children?.also { transItems(it, item.id)  }
        }
    }

    fun transItems(items: Array<MenuItem>, pid: String? = null) {
        for((index, item) in items.withIndex()) {
            item.pid = pid ?: "0"
            item.id = item.id ?: (pid?.let { "$pid-${index+1}" } ?: "${index+1}")
            item.children?.also { transItems(it, item.id)  }
        }
    }

    companion object {
        internal val log = LoggerFactory.getLogger(FileMenuStore::class.java)
        private val mapper = ObjectMapper().apply {
            disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
            registerModule(JavaTimeModule())
        }

        fun <T> parseObject(jsonData: String, clazz: Class<T>): T {
            return mapper.readValue(jsonData, clazz)
        }
    }
}