const express = require('express'),
    path = require("path"),
    fs = require("fs"),
    WebSocket = require("ws"),
    chokidar = require("chokidar"),
    sharp = require("sharp")

const PORT = process.env.PORT || 8080

var app = express()

var lanyardData = "Nothing Fetched yet!"

var sockets = []

var pfpSeason = "default"

var violetSpins = 0

var lastActivity

var configPath = path.join(__dirname, "config")
if (!fs.existsSync(configPath)) {
    fs.mkdirSync(configPath)
}

var dataPath = path.join(__dirname, "data")
if (!fs.existsSync(dataPath)) {
    fs.mkdirSync(dataPath)
} else if (fs.existsSync(path.join(dataPath, "spins"))) {
    violetSpins = Number(fs.readFileSync(path.join(dataPath, "spins")))
}


var configsC = ["socials.json"]
var configsB = ["videos.json"]

for (var i = 0; i < configsC.length; i++) {
    var file = configsC[i]
    var filePath = path.join(configPath, file)
    if (!fs.existsSync(filePath)) {
        fs.writeFileSync(filePath, "{}")
    }
}

for (var i = 0; i < configsB.length; i++) {
    var file = configsB[i]
    var filePath = path.join(configPath, file)
    if (!fs.existsSync(filePath)) {
        fs.writeFileSync(filePath, "[]")
    }
}

function randomFileInDir(directory) {
    var dir = fs.readdirSync(directory)
    return path.join(directory, dir[Math.floor(Math.random() * dir.length)])
}

app.get("/", (req, res) => {
    var docs = fs.readFileSync(path.join(__dirname, "basicDocs.json"))
    docs = JSON.parse(docs)
    res.send(docs)
})

app.get("/v1/pfp", async (req, res) => {
    res.setHeader("Content-Type", "image/png")

    var time = new Date(Date.now())
    // if ([12].includes(time.getMonth() + 1)) {
    //     pfpSeason = "christmas"
    // }
    
    var pfpConfig = JSON.parse(fs.readFileSync(path.join(__dirname, "PFPs.json")))[pfpSeason]
    var characterNumb = (time.getDay()) % pfpConfig.length
    var char = pfpConfig[characterNumb]
    var pfps = char.pfps
    
    var pfpPool = pfps
    var rand = Math.floor(Math.random() * pfpPool.length)
    var pfp = path.join(__dirname, char.pfpRoot, pfpPool[rand])

    var pfpRaw = fs.readFileSync(pfp)

    var pfpWidth = Number(req.query.width) || 256
    var pfpHeight = Number(req.query.height) || 256

    const converted = await sharp(pfpRaw)
    .resize(pfpWidth, pfpHeight)
    .png({ progressive: true })
    .toBuffer()

    res.send(converted)
})

app.get("/v1/lanyard", (req, res) => {
    res.send(lanyardData)
})

app.get("/v1/spins", (req, res) => {
    res.send(violetSpins.toString())
})

app.get("/v1/socials", (req, res) => {
    res.sendFile(path.join(configPath, "socials.json"))
})

function getVideo() {
    var videoQueue = JSON.parse(fs.readFileSync(path.join(dataPath, "videos.json")))

    var newQueue = []
    for (var i = 0; i < videoQueue.length; i++) {
        var video = videoQueue[i]
        if (video.ends > Date.now()) {
            newQueue.push(video)
        }
    }
    videoQueue = newQueue
    fs.writeFileSync(path.join(dataPath, "videos.json"), JSON.stringify(newQueue))

    var oldest = videoQueue[0]

    for (var i = 0; i < videoQueue.length; i++) {
        var video = videoQueue[i]
        if (video.ends < (oldest.ends)) {
            oldest = video
        }
    }

    return oldest
}

// app.listen(PORT, () => {
//     console.log("API is now listening on port 8080!")
// })

function socketeer() {
    var lanyard = new WebSocket('wss://lanyard.violets-purgatory.dev/socket')

    function beat(dur) {
        lanyard.send(JSON.stringify({
            op: 3
        }))
        setTimeout(() => {
            beat(dur)
        }, dur);
    }

    lanyard.addEventListener("message", async (res) => {
        var data = JSON.parse(res.data)
        if (data.op == 1) {
            beat(data.d.heartbeat_interval)
            lanyard.send(JSON.stringify({
                op: 2,
                d: {
                    subscribe_to_id: "534132311781015564"
                }
            }))
        } else if (data.op == 0) {
            lanyardData = data
            lanyardData.d.socials = JSON.parse(fs.readFileSync(path.join(configPath, "socials.json")))
            lanyardData.d.video = getVideo()
            var newArr = []
            for (var i = 0; i < lanyardData.d.activities.length; i++) {
                var activity = lanyardData.d.activities[i]
                
                if (activity.type == 2) {
                    // if (activity.name == "Spotify") {
                    if (activity.assets) {
                        activity.song = activity.details
                        activity.album = activity.assets.large_text
                        activity.artist = activity.state
                    }
                }

                if (activity.type != 4) {
                    newArr.push(activity)
                } else if (activity.type == 4) {
                    lanyardData.d.custom_status = {
                        "text": activity.state
                    }
                    if (activity.emoji) {
                        lanyardData.d.custom_status.emoji = activity.emoji
                    }
                }
            }

            lanyardData.d.activities = newArr

            if (lanyardData.d.discord_status == "offline") {
                lanyardData.d.activityChanged = false
            } else {
                lanyardData.d.activityChanged = lastActivity != JSON.stringify(lanyardData.d.activities)
            }
            lastActivity = JSON.stringify(lanyardData.d.activities)

            for (let index = 0; index < sockets.length; index++) {
                var socketData = sockets[index]
                var socket = socketData.socket;
                socket.send(JSON.stringify(lanyardData))

                if ((Date.now() - socketData.lastPing) > 120000) {
                    sockets.splice(index, 1)
                }
            }
        }
    })

    lanyard.on('close', () => {
        console.log("Disconnected")
        setTimeout(() => {
            socketeer()
        }, 60000)
    })
}

socketeer()

// wsServer = new WebSocket.WebSocketServer({ port: 8090 })

wsServer = WebSocket.Server;
let server = require('http').createServer()
wsServer = new wsServer({
    server: server,
    perMessageDeflate: false
})
server.on('request', app)

wsServer.on("connection", function connection(socket) {
    socket.on('message', function message(data) {
        data = JSON.parse(data)
        if (data.op == 3) {
            for (let index = 0; index < sockets.length; index++) {
                const socketData = sockets[index];
                if (socketData.socket == socket) {
                    sockets[index].lastPing = Date.now()
                }
            }

            socket.send(`{"op": 3}`)
        } else if (data.op == 4) {
            violetSpins += 1
            if (violetSpins % 10 == 0) {
                fs.writeFileSync(path.join(dataPath, "spins"), violetSpins.toString())
            }
            for (var i = 0; i < sockets.length; i++) {
                var soc = sockets[i].socket
                soc.send(`{"op": 4, "spins": ${violetSpins}}`)

            }
        } else {
            console.log(data)
        }
    })

    socket.send(JSON.stringify(lanyardData))
    socket.send(`{ "op": 1 }`)
    socket.send(`{"op": 4, "spins": ${violetSpins}}`)
    
    sockets.push({ socket, lastPing: Date.now() })
})

server.listen(PORT, function () {
    console.log("API & Websocket now on port: " + PORT)
})

process.on('uncaughtException', (err, origin) => {
    fs.writeSync(
      process.stderr.fd,
      `Caught exception: ${err}\n` +
      `Exception origin: ${origin}`,
    );
  });  

chokidar.watch(path.join(configPath, "videos.json")).on("change", () => {
    var videos = JSON.parse(fs.readFileSync(path.join(configPath, "videos.json")))

    if (!fs.existsSync(path.join(dataPath, "videos.json"))) {
        fs.writeFileSync(path.join(dataPath, "videos.json"), "[]")
    }

    var videoQueue = JSON.parse(fs.readFileSync(path.join(dataPath, "videos.json")))

    var latestTime = Date.now()
    for (var i = 0; i < videoQueue.length; i++) {
        var vid = videoQueue[i];
        if (Number(vid.ends) > latestTime) {
            latestTime = Number(vid.ends)
        }
    }

    var newVideos = []

    for (var i = 0; i < videos.length; i++) {
        latestTime += 604800000
        var url = videos[i]
        newVideos.push({
            "url": url,
            "ends": latestTime
        })
    }

    videoQueue = videoQueue.concat(newVideos)

    fs.writeFileSync(path.join(dataPath, "videos.json"), JSON.stringify(videoQueue))

    fs.writeFileSync(path.join(configPath, "videos.json"), "[]")
})