// Load up the discord.js library
const Discord = require("discord.js");
// Load up the line reader and cron libraries
const lineByLine = require('n-readlines');
const cron = require('node-cron');

// This is your client. Some people call it `bot`, some people call it `self`, 
// some might call it `cootchie`. Either way, when you see `client.something`, or `bot.something`,
const client = new Discord.Client();

// Here we load the config.json file that contains our token and our prefix values. 
const config = require("./config.json");

// config.token contains the bot's token
// config.prefix contains the message prefix.
// config.client_file_path contains the file "client.txt" path.
const filePath = config.client_file_path;
// config.string_to_search contains the string you want to send message.
const stringToSearch = config.string_to_search;
// config.channel_id contains the id of the channel you want to send message to.
const channelID = config.channel_id;
// config.bot_activity contains the activity name for bot.
const bot_activity = config.bot_activity;
// config.interval contains interval in seconds between reading file.
const interval = config.interval;
// config.interval_between_message_sec contains interval in seconds between 2 messages.
const interval_between_message_sec = config.interval_between_message_sec;
// config.text_to_find contains text that you want to find in message for replacement.
const text_to_find = config.text_to_find;
// config.text_to_replace contains text that you want to replace with.
const text_to_replace = config.text_to_replace;

// Regex to find timestamp
const timeStampRegEx = new RegExp('^([0-9]{4}\/(0[1-9]|1[0-2])\/(0[1-9]|[1-2][0-9]|3[0-1]) (2[0-3]|[01][0-9]):[0-5][0-9]:[0-5][0-9])', "g");
// Regex to find message
const messageRegEx = new RegExp("(?<=&<" + stringToSearch + ">).+", "g");
// const messageRegEx = new RegExp("(?<=<" + stringToSearch + ">).+", "g");

let lastTimeStamp = null;
let currentTimeStamp = null;
let channel = null;
let line;
let liner;
let messageToSend = '';
let message = '';
let lastMessage = '';
let userName = '';
let i = 0;

async function readMessagesFromFile() {
    // select file
    liner = new lineByLine(filePath);

    // select channel by id
    channel = await client.channels.fetch(channelID);

    while (line = liner.next()) {

        messageToSend = null;
        userName = null;
        message = '';

        // Get line in string
        line = line.toString();

        // Get message from line
        messageToSend = line.match(messageRegEx);

        // Check if message is valid
        if (messageToSend == null || messageToSend.length <= 0) {
            continue;
        }

        // get timestamp of current line
        currentTimeStamp = line.match(timeStampRegEx);

        // Check if line is traversed before or not
        if ((lastTimeStamp != null && currentTimeStamp != null) && (new Date(lastTimeStamp[0]) >= new Date(currentTimeStamp[0]))) {
            continue;
        }

        userName = messageToSend[0].match(/^(.+?):/g)

        messageToSend = messageToSend[0].match(/(?<=:).*/g)

        if (userName === null) continue;

        userName = "**" + userName[0].trim() + "**"


        messageToSend = messageToSend[0].replace(text_to_find, text_to_replace)

        // Sleep for given interval
        await sleep(interval_between_message_sec * 1000);





		// YOU CAN CUSTOM TAILOR THE BOT's FINAL OUTPUT MESSAGE HERE

		//Additional Examples:
        //message = messageToSend;
		//message = "Random Text" + "Random Text" + messageToSend;
        message = userName + messageToSend;





        // Sending message to channel after Logging it out
        if (line && message != '' & message != lastMessage) {
            console.log(i + " ==> " + message)
            await sendMessage(channel, message)
        }

        // Assigning current timestamp to lasttimestamp
        lastTimeStamp = currentTimeStamp;
        i++;
    }
}

async function sendMessage(channel, messageToSend) {

    try {
        lastMessage = messageToSend;
        await channel.send(messageToSend)
    } catch (error) {
        return false;
    }

    return true;
}

// Scheduling message sending process  */5 * * * * *
cron.schedule(`*/${interval} * * * * *`, () => {
    console.log('=== Reading file and sending message ===');
    readMessagesFromFile();
});

// Sleep function
function sleep(ms, message) {
    // console.log("=== Sleeping === ")
    return new Promise(resolve => setTimeout(resolve, ms));
}

// ON BOT START:
client.on("ready", () => {
    // This event will run if the bot starts, and logs in, successfully.
    console.log(`Bot has started, with ${client.users.size} users, in ${client.channels.size} channels of ${client.guilds.size} guilds.`);
    // Example of changing the bot's playing game to something useful. `client.user` is what the
    // docs refer to as the "ClientUser".
    client.user.setActivity(`${bot_activity}`);

    // fire the event when bot starts 
    readMessagesFromFile();
});

client.on("guildCreate", guild => {
    // This event triggers when the bot joins a guild.
    console.log(`New guild joined: ${guild.name} (id: ${guild.id}). This guild has ${guild.memberCount} members!`);
    client.user.setActivity(`Serving ${client.guilds.size} servers`);
});

client.on("guildDelete", guild => {
    // this event triggers when the bot is removed from a guild.
    console.log(`I have been removed from: ${guild.name} (id: ${guild.id})`);
    client.user.setActivity(`Serving ${client.guilds.size} servers`);
});

client.login(config.token);