import {Controller, view, Injectable, Inject, Routing, redirect, plaintext} from '@extollo/lib'
import {Home} from './Home.controller'
import {FoodBlog as FoodBlogService, FoodBlogPostFrontMatter} from '../../services/blog/FoodBlog.service'
import {BlogPost} from '../../services/blog/AbstractBlog.service'
import {Country, countryNames, isCountry, mapPositions} from '../../services/blog/countries'

/**
 * FoodBlog Controller
 * ------------------------------------
 * Put some description here.
 */
@Injectable()
export class FoodBlog extends Controller {
    @Inject()
    protected readonly blog!: FoodBlogService

    @Inject()
    protected readonly routing!: Routing

    public async index() {
        const home = <Home> this.make(Home)
        return view('food:welcome', {
            ...home.getThemeCSS(),
            ...(await this.getBlogData()),
            posts: (await this.blog.getAllPosts())
                .take(10)
                .all(),
        })
    }

    public async archive() {
        const home = <Home> this.make(Home)

        const postsByCountry = (await this.blog.getAllPosts())
            .reverse()
            .groupBy(p => p.country)

        return view('food:archive', {
            ...home.getThemeCSS(),
            ...(await this.getBlogData()),
            postsByCountry,
            postCountries: Object.keys(postsByCountry),
        })
    }

    public async feeds() {
        const home = <Home> this.make(Home)
        return view('food:feeds', {
            ...home.getThemeCSS(),
            ...(await this.getBlogData()),
        })
    }

    public async about() {
        const home = <Home> this.make(Home)
        return view('food:about', {
            ...home.getThemeCSS(),
            ...(await this.getBlogData()),
        })
    }

    public async country() {
        const country = this.request.safe('country').string().toUpperCase()
        if ( !isCountry(country) ) {
            return redirect('/food')
        }

        const home = <Home> this.make(Home)
        return view('food:country', {
            ...home.getThemeCSS(),
            ...(await this.getBlogData()),
            mapPosition: mapPositions[country],
            country,
            countryBlurb: await this.blog.getCountryBlurb(country),
            posts: (await this.blog.getAllPosts())
                .where('country', '=', country)
                .all(),
        })
    }

    public async rss() {
        const feed = await this.blog.getFeed()
        return plaintext(feed.rss2()).contentType('application/rss+xml; charset=UTF-8')
    }

    public async atom() {
        const feed = await this.blog.getFeed()
        return plaintext(feed.atom1()).contentType('application/atom+xml; charset=UTF-8')
    }

    public async json() {
        const feed = await this.blog.getFeed()
        return plaintext(feed.json1()).contentType('application/feed+json; charset=UTF-8')
    }

    public async post() {
        const home = <Home> this.make(Home)
        const slug = this.request.safe('slug').string()
        const post = await this.blog.getPost(slug)
        if ( !post ) {
            return view('food:404', {
                ...home.getThemeCSS(),
                ...(await this.getBlogData()),
                title: 'Post Not Found',
                slug,
            })
        }

        return view('food:post', {
            ...home.getThemeCSS(),
            ...(await this.getBlogData()),
            post,
            mapPosition: mapPositions[post.country],
            title: post.title,
            renderedPost: await this.blog.renderPost(post.slug),
        })
    }

    private static cachedBlogData: any = undefined
    public async getBlogData(): Promise<any> {
        if ( FoodBlog.cachedBlogData ) {
            return FoodBlog.cachedBlogData
        }

        const postsByCountry = (await this.blog.getAllPosts())
            .groupBy(p => p.country)

        const mapValues: any = {}
        for ( const country of Object.keys(postsByCountry) ) {
            const date = postsByCountry[country][0].date
            mapValues[country] = {
                posts: postsByCountry[country].length,
                visited: date.toLocaleString('default', { month: 'long' }) + ' ' + date.getFullYear(),
                link: `/food/c/${country}`,
            }
        }

        return (FoodBlog.cachedBlogData = {
            mapValues,
            blogCountry: (code: Country): string => `${code} - ${countryNames[code]}`,
            blogUrl: (post: BlogPost<FoodBlogPostFrontMatter>): string => this.blog.getUrl(post),
            blogDate: (date: Date): string => {
                const year = date.getFullYear()
                let month = String(date.getMonth() + 1)
                if ( month.length < 2 ) month = `0${month}`
                let day = String(date.getDate())
                if ( day.length < 2 ) day = `0${day}`
                return `${year}-${month}-${day}`
            },
        })
    }
}
