import * as electron from 'electron';
import * as DiscordRPC from 'discord-rpc'
export default class DiscordRPCPlugin {
	/**
	 * Private variables for interaction in plugins
	 */
	private _win: any;
	private _app: any;
    private _discord: any;
    private connect(clientId: any) {
        this._discord = { isConnected: false };
        if (this._win.store.store.general.discord_rpc == 0 || this._discord.isConnected) return;

        DiscordRPC.register(clientId) // Apparently needed for ask to join, join, spectate etc.
        const client = new DiscordRPC.Client({ transport: "ipc" });
        this._discord = Object.assign(client, { error: false, activityCache: null, isConnected: false });

        // Login to Discord
        this._discord.login({ clientId })
            .then(() => {
                this._discord.isConnected = true;
            })
            .catch((e : any) => console.error(`[DiscordRPC][connect] ${e}`));

            this._discord.on('ready', () => {
            console.log(`[DiscordRPC][connect] Successfully Connected to Discord. Authed for user: ${client.user.username} (${client.user.id})`);
        })

        // Handles Errors
        this._discord.on('error', (err: any) => {
            console.error(`[DiscordRPC] ${err}`);
            this.disconnect()
            this._discord.isConnected = false;
        });
    }

        /**
     * Disconnects from Discord RPC
     */
    private disconnect() {
        if (this._win.store.store.general.discord_rpc == 0 || !this._discord.isConnected) return;
    
        try {
            this._discord.destroy().then(() => {
                this._discord.isConnected = false;
                console.log('[DiscordRPC][disconnect] Disconnected from discord.')
            }).catch((e : any) => console.error(`[DiscordRPC][disconnect] ${e}`));
        } catch (err) {
                console.error(err)
        }
    }

    /**
     * Sets the activity of the client
     * @param {object} attributes
     */
    private updateActivity(attributes : any) {
        if (this._win.store.store.general.discord_rpc == 0) return;

        if (!this._discord.isConnected) {
            this._discord.clearActivity().catch((e : any) => console.error(`[DiscordRPC][updateActivity] ${e}`));
            return;
        }

        // console.log('[DiscordRPC][updateActivity] Updating Discord Activity.')

        const listenURL = `https://cider.sh/p?s&id=${attributes.playParams.id}` // cider://play/s/[id] (for song) 
            //console.log(attributes)

        interface ActObject {
            details?: any,
            state?: any,
            startTimestamp?: any,
            endTimestamp?: any,
            largeImageKey? : any,
            largeImageText?: any,
            smallImageKey?: any,
            smallImageText?: any,
            instance: true,
            buttons?: [
                { label: "Listen on Cider", url?: any },
            ]
        }   

        let ActivityObject : ActObject | null = {
            details: attributes.name,
            state: `by ${attributes.artistName}`,
            startTimestamp: attributes.startTime,
            endTimestamp: attributes.endTime,
            largeImageKey : (attributes.artwork.url.replace('{w}', '1024').replace('{h}', '1024')) ?? 'cider',
            largeImageText: attributes.albumName,
            smallImageKey: (attributes.status ? 'play' : 'pause'),
            smallImageText: (attributes.status ? 'Playing' : 'Paused'),
            instance: true,
            buttons: [
                { label: "Listen on Cider", url: listenURL },
            ]
        };
        if (ActivityObject.largeImageKey == "" || ActivityObject.largeImageKey == null) {
            ActivityObject.largeImageKey = (this._win.store.store.general.discord_rpc == 1) ? "cider" : "logo"
        }

        // Remove the pause/play icon and test for clear activity on pause
        if (this._win.store.store.general.discordClearActivityOnPause == 1) {
            delete ActivityObject.smallImageKey
            delete ActivityObject.smallImageText
        }

        // Deletes the timestamp if its not greater than 0
        if (!((new Date(attributes.endTime)).getTime() > 0)) {
            delete ActivityObject.startTimestamp
            delete ActivityObject.endTimestamp
        }

        // Artist check
        if (!attributes.artistName) {
            delete ActivityObject.state
        }

        // Album text check
        if (!ActivityObject.largeImageText || ActivityObject.largeImageText.length < 2) {
            delete ActivityObject.largeImageText
        }

        // Checks if the name is greater than 128 because some songs can be that long
        if (ActivityObject.details.length > 128) {
            ActivityObject.details = ActivityObject.details.substring(0, 125) + '...'
        }




        // Check if its pausing (false) or playing (true)
        if (!attributes.status) {
            if (this._win.store.store.general.discordClearActivityOnPause == 1) {
                this._discord.clearActivity().catch((e : any) => console.error(`[DiscordRPC][clearActivity] ${e}`));
                ActivityObject = null 
            } else {
                delete ActivityObject.startTimestamp
                delete ActivityObject.endTimestamp
                ActivityObject.smallImageKey = 'pause'
                ActivityObject.smallImageText = 'Paused'
            }
        }


        if (ActivityObject && ActivityObject !== this._discord.activityCache && ActivityObject.details && ActivityObject.state) {
            try {
                //  console.log(`[DiscordRPC][setActivity] Setting activity to ${JSON.stringify(ActivityObject)}`);
                this._discord.setActivity(ActivityObject)
                this._discord.activityCache = ActivityObject
            } catch (err) {
                console.error(`[DiscordRPC][setActivity] ${err}`)
            }

        }
    }


    /**
     * Base Plugin Details (Eventually implemented into a GUI in settings)
     */
    public name: string = 'DiscordRPCPlugin';
    public description: string = 'Discord RPC plugin for Cider';
    public version: string = '0.0.1';
    public author: string = 'vapormusic / Cider Collective';

    /**
     * Runs on plugin load (Currently run on application start)
     */
    constructor(app: any) {
		this._app = app;
	}

    /**
     * Runs on app ready
     */
    onReady(win: any): void {
		this._win = win;
        this.connect((this._win.store.store.general.discord_rpc == 1) ? '911790844204437504' : '886578863147192350'); 
        // electron.ipcMain.on("forceUpdateRPC", (event, attributes : object) => {          
        //     this.updateActivity(attributes)
        // });
    }

    /**
     * Runs on app stop
     */
    onBeforeQuit(): void {
        console.log('Example plugin stopped');
    }

    /**
     * Runs on playback State Change
     * @param attributes Music Attributes (attributes.state = current state)
     */
    onPlaybackStateDidChange(attributes: object): void {
        this.updateActivity(attributes)
    }

    /**
     * Runs on song change
     * @param attributes Music Attributes
     */
    onNowPlayingItemDidChange(attributes: object): void {
        this.updateActivity(attributes)
    }

}
