Newer
Older
Twilight / src / main / kotlin / net / taehui / twilight / system / AutoSystem.kt
@Taehui Taehui on 8 Jul 9 KB v1.0-SNAPSHOT
package net.taehui.twilight.system

import net.taehui.twilight.Logger
import net.taehui.twilight.TwilightComponent
import org.apache.commons.io.FilenameUtils
import java.nio.file.*
import java.util.concurrent.Executors
import java.util.concurrent.ScheduledExecutorService
import java.util.concurrent.ScheduledFuture
import java.util.concurrent.TimeUnit

class AutoSystem : AutoCloseable, Logger {
    private val ses: ScheduledExecutorService = Executors.newSingleThreadScheduledExecutor {
        Executors.defaultThreadFactory().newThread(it).apply {
            isDaemon = true
        }
    }
    private val ws = FileSystems.getDefault().newWatchService()
    private var futureVote: ScheduledFuture<*>? = null
    private var isPendingVote = false
    private var futureConfigure: ScheduledFuture<*>? = null
    private var isPendingConfigure = false
    private var futureAwilight: ScheduledFuture<*>? = null
    private var futureTitle: ScheduledFuture<*>? = null
    private var isPendingTitle = false
    private var futureLevel: ScheduledFuture<*>? = null
    private var isPendingLevel = false
    private var futureAbility: ScheduledFuture<*>? = null
    private var isPendingAbility = false
    private var futureAbilityClass: ScheduledFuture<*>? = null
    private var isPendingAbilityClass = false
    private var futureEdge: ScheduledFuture<*>? = null
    private var isPendingEdge = false

    init {
        Paths.get(".").register(ws, StandardWatchEventKinds.ENTRY_MODIFY)
        TwilightComponent.SYSTEM_ENTRY_PATH.register(ws, StandardWatchEventKinds.ENTRY_MODIFY)
        TwilightComponent.DEFAULT_NOTE_ENTRY.register(ws, StandardWatchEventKinds.ENTRY_MODIFY)
        TwilightComponent.DEFAULT_UI_ENTRY.register(ws, StandardWatchEventKinds.ENTRY_MODIFY)
        TwilightComponent.TITLE_ENTRY_PATH.register(ws, StandardWatchEventKinds.ENTRY_MODIFY)
        TwilightComponent.LEVEL_ENTRY_PATH.register(ws, StandardWatchEventKinds.ENTRY_MODIFY)
        TwilightComponent.VOTE_ENTRY_PATH.register(ws, StandardWatchEventKinds.ENTRY_MODIFY)
        TwilightComponent.ABILITY_ENTRY_PATH.register(ws, StandardWatchEventKinds.ENTRY_MODIFY)
        TwilightComponent.ABILITY_CLASS_ENTRY_PATH.register(ws, StandardWatchEventKinds.ENTRY_MODIFY)
        TwilightComponent.EDGE_ENTRY_PATH.register(ws, StandardWatchEventKinds.ENTRY_MODIFY)
        Thread {
            try {
                while (true) {
                    val tws = ws.take()
                    tws.pollEvents().forEach {
                        fun loadConfigure() {
                            if (isPendingConfigure) {
                                isPendingConfigure = false
                            } else {
                                futureConfigure?.cancel(true)
                                futureConfigure = ses.schedule({
                                    isPendingConfigure = true
                                    Configure.loadConfigure()
                                }, 1, TimeUnit.SECONDS)
                            }
                        }

                        val filePath = (tws.watchable() as Path).resolve(it.context() as Path)
                        val fileName = filePath.fileName.toString()
                        when (filePath.parent.fileName.toString()) {
                            "Note", "UI" -> {
                                if (FilenameUtils.isExtension(fileName, "zip") || FilenameUtils.isExtension(
                                        fileName,
                                        "rar"
                                    )
                                ) {
                                    loadConfigure()
                                }
                            }

                            "Vote" -> {
                                if (FilenameUtils.isExtension(fileName, "json")) {
                                    if (isPendingVote) {
                                        isPendingVote = false
                                    } else {
                                        futureVote?.cancel(true)
                                        futureVote = ses.schedule(
                                            {
                                                isPendingVote = true
                                                VoteSystem.loadVote()
                                            }, 1, TimeUnit.SECONDS
                                        )
                                    }
                                }
                            }

                            "Title" -> {
                                if (FilenameUtils.isExtension(fileName, "json")) {
                                    if (isPendingTitle) {
                                        isPendingTitle = false
                                    } else {
                                        futureTitle?.cancel(true)
                                        futureTitle = ses.schedule(
                                            {
                                                isPendingTitle = true
                                                TitleSystem.loadTitle()
                                            }, 1, TimeUnit.SECONDS
                                        )
                                    }
                                }
                            }

                            "Level" -> {
                                if (isPendingLevel) {
                                    isPendingLevel = false
                                } else {
                                    futureLevel?.cancel(true)
                                    futureLevel = ses.schedule(
                                        {
                                            isPendingLevel = true
                                            LevelSystem.loadLevel()
                                        }, 1, TimeUnit.SECONDS
                                    )
                                }
                            }

                            "Ability" -> {
                                when (fileName) {
                                    "Default.json" -> {
                                        if (isPendingAbility) {
                                            isPendingAbility = false
                                        } else {
                                            futureAbility?.cancel(true)
                                            futureAbility = ses.schedule(
                                                {
                                                    isPendingAbility = true
                                                    AbilitySystem.loadAbility()
                                                }, 1, TimeUnit.SECONDS
                                            )
                                        }}
                                }
                            }

                            "Ability Class" -> {
                                if (isPendingAbilityClass) {
                                    isPendingAbilityClass = false
                                } else {
                                    futureAbilityClass?.cancel(true)
                                    futureAbilityClass = ses.schedule(
                                        {
                                            isPendingAbilityClass = true
                                            AbilityClassSystem.loadAbilityClass()
                                        }, 1, TimeUnit.SECONDS
                                    )
                                }
                            }

                            "Edge" -> {
                                if (isPendingEdge) {
                                    isPendingEdge = false
                                } else {
                                    futureEdge?.cancel(true)
                                    futureEdge = ses.schedule(
                                        {
                                            isPendingEdge = true
                                            EdgeSystem.loadEdge()
                                        }, 1, TimeUnit.SECONDS
                                    )
                                }
                            }

                            "System" -> {
                                when (fileName) {
                                    "Awilight.py" -> {
                                        futureAwilight?.cancel(true)
                                        futureAwilight = ses.schedule(
                                            { AwilightHandler.loadAwilight() },
                                            1,
                                            TimeUnit.SECONDS
                                        )
                                    }
                                }
                            }

                            "." -> {
                                when (fileName) {
                                    "Configure.json" -> loadConfigure()
                                }
                            }
                        }
                    }
                    tws.reset()
                }
            } catch (_: ClosedWatchServiceException) {
            }
        }.apply { isDaemon = true }.start()
    }

    override fun close() {
        ws.close()
        ses.shutdown()
    }
}