import {
    Controller,
    view,
    Injectable,
    SecurityContext,
    Inject,
    Collection,
    Config,
    Routing,
    file,
    Application,
    make,
    Valid,
} from '@extollo/lib'
import {WorkItem} from '../../models/WorkItem.model'
import {FeedPost} from '../../models/FeedPost.model'
import {ContactForm} from '../../types/ContactForm.type'
import {ContactSubmission} from '../../models/ContactSubmission.model'
import {Gotify} from 'gotify'

@Injectable()
export class Home extends Controller {
    @Inject()
    protected readonly security!: SecurityContext

    @Inject()
    protected readonly config!: Config

    @Inject()
    protected readonly routing!: Routing

    @Inject()
    protected readonly gotify!: Gotify

    public async welcome(feedPosts: Collection<FeedPost>) {
        const workItems = await this.getWorkItems()

        return view('welcome', {
            feedPosts: feedPosts.toArray(),
            workItemGroups: workItems.groupBy(item => item.startDate.getFullYear()),
            workItemYears: workItems.map(item => item.startDate.getFullYear())
                .unique()
                .toArray(),
            workItemHiddenYears: workItems.filter(item => item.endDate)
                .map(item => item.startDate.getFullYear())
                .unique()
                .toArray()
        })
    }

    public technical() {
        const isOptOut = this.request.cookies.has(this.config.get('app.analytics.optOutCookie'))

        return view('technical', {
            isOptOut,
        })
    }

    public optOutPrompt() {
        return view('message', {
            title: 'Analytics Opt-Out',
            message: 'This will set a cookie to disable analytics recording in your browser on all <code>*.garrettmills.dev</code> sites. Continue?',
            buttonAction: this.routing.getNamedPath('opt-out').toRemote,
            buttonMethod: 'post',
        })
    }

    public optOut() {
        this.request.cookies.set(
            this.config.get('app.analytics.optOutCookie'),
            true,
            {
                expires: new Date(Date.now() + (1000 * 60 * 60 * 24 * 365 * 100)),
                secure: true,
                httpOnly: true,
                path: '/',
            },
        )

        return view('message', {
            title: 'Analytics Opt-Out',
            message: 'You have been opted-out of analytics recording.',
            buttonAction: this.routing.getNamedPath('home').toRemote,
        })
    }

    protected async getWorkItems(): Promise<Collection<WorkItem>> {
        const query = WorkItem.query<WorkItem>()
            .orderByDescending('start_date')

        if ( !this.security.hasUser() ) {
            query.where('visible', '=', true)
        }

        return query.get().collect()
    }

    favicon() {
        return file(
            Application.getApplication()
                .appPath('resources', 'assets', 'favicon', 'favicon.ico')
        )
    }

    humans() {
        return Application.getApplication()
            .appPath('resources', 'assets', 'humans.txt')
            .read()
    }

    async contact(data: Valid<ContactForm>) {
        const submission = make<ContactSubmission>(ContactSubmission)
        submission.name = data.name
        submission.email = data.email
        submission.message = data.message
        await submission.save()

        this.gotify.send({
            app: this.config.get('gotify.app'),
            title: `Contact form submission from ${data.name}`,
            message: [
                `From: ${data.name}`,
                `E-mail: ${data.email}`,
                'Message:',
                data.message,
            ].join('\n'),
        })

        return view('message', {
            title: 'Message Sent',
            message: 'Your message has been sent. Thanks! I\'ll be in touch soon.',
            buttonAction: this.routing.getNamedPath('home').toRemote,
        })
    }
}
