import { Injectable } from '@angular/core';

import { XHR } from '../../xhr';
import { Parser } from 'xml2js';
import * as moment from 'moment';


const NEWS_STORAGE_KEY: string = 'lvemanager-news-titles';

@Injectable()
export class EventService {
    messages: NewsItem[] = [];
    newCount: number = 0;
    visible: boolean = false;
    constructor(private request: XHR) {
        this.init();
    }

    async init() {
        this.messages = await this.getMessages();
    }

    async loadMessages() {
        try {
            return await this.getRSSNews();
        } catch (e) {
            return [];
        }
    }

    getSaved(): string[] {
        try {
            return JSON.parse(localStorage.getItem(NEWS_STORAGE_KEY) || '[]');
        } catch (e) {
            return [];
        }
    }

    async getMessages() {
        try {
            let messages = await this.loadMessages();
            messages.forEach(message => {
                message.latest = !this.getSaved().includes(message.link);

                let curDate = moment(
                    message.pubDate, 'ddd, DD MMM YYYY HH:mm:ss +Z', 'en'
                ).format('DD.MM.YYYY');
                let today = moment().format('DD.MM.YYYY');

                let format = (curDate === today) ? 'HH:mm' : 'DD.MM HH:mm';

                message.pubDate = moment(
                    message.pubDate, 'ddd, DD MMM YYYY HH:mm:ss +Z', 'en'
                ).format(format);
            });
            this.newCount = messages.map(message => message.link)
                .filter(message => !this.getSaved().includes(message))
                .length;
            this.visible = !!this.newCount;
            return messages;
        } catch (e) {
            return [];
        }
    }

    saveMessages() {
        if (!this.newCount) {
            return;
        }

        const saved = this.getSaved();
        const newNewsTitles = saved.concat(
            this.messages
                .map(message => message.link)
                .filter(message => !saved.includes(message))
        );

        localStorage.setItem(NEWS_STORAGE_KEY, JSON.stringify(newNewsTitles));
        this.newCount = 0;
    }

    markAsRead(link: string) {
        let curMessage = this.messages.find(message => message.link === link);
        const saved = this.getSaved();
        if (curMessage && curMessage.latest && !saved.includes(link)) {
            saved.push(link);
            localStorage.setItem(NEWS_STORAGE_KEY, JSON.stringify(saved));
            this.newCount--;
            curMessage.latest = false;
        }
    }

    public async getRSSNews(category = 'CloudLinux OS'): Promise<NewsItem[]> {
        let data: DataOfRSSNews;
        try {
            data = await this.request.post({
                command: 'spa-get-rss-news'
            });
        } catch (e) {
            data.content = '';
        }

        let parser = new Parser({
            explicitArray: false,
            ignoreAttrs: true,
            explicitRoot: false
        });
        return new Promise<NewsItem[]>((resolve, reject) => {
            parser.parseString(data.content, (err, result: DataOfXMLNewsFile) => {
                if (err) {
                    reject(err);
                    return;
                }
                resolve(
                    result.channel.item.filter(_item =>
                        _item.category.includes(category)
                    )
                );
            });
        });
    }
}

interface DataOfRSSNews {
    result: string;
    content: string;
    age: number;
}

interface DataOfXMLNewsFile {
    channel: {
        item: NewsItem[]
    };
}

interface NewsItem {
    author: string;
    category: string;
    description: string;
    guid: string;
    link: string;
    pubDate: string;
    title: string;
    latest: boolean;
}
