const { Model } = require('flitter-orm')
const uuid = require('uuid').v4

/*
 * OAuth2 Client Model
 * ---------------------------------------------------
 * Represents a single OAuth2 client. This class contains logic
 * to create/update/delete the associated Flitter-Auth Oauth2Client
 * instance.
 */
class ClientModel extends Model {
    static get services() {
        return [...super.services, 'models']
    }

    static get schema() {
        return {
            name: String,
            uuid: {type: String, default: uuid},
            secret: {type: String, default: uuid},
            active: {type: Boolean, default: true},
            api_scopes: [String],
            redirect_url: String,
        }
    }

    async application() {
        const Application = this.models.get('Application')
        return Application.findOne({ active: true, oauth_client_ids: this.id })
    }

    async update_auth_client() {
        const Oauth2Client = this.models.get('auth::Oauth2Client')
        let client = await Oauth2Client.findOne({ clientID: this.uuid })

        // There's an associated client, but we're not active, so delete the assoc
        if ( client && !this.active ) {
            await client.delete()
            return
        }

        if ( !client ) {
            client = new Oauth2Client({
                grants: ['authorization_code'],
            })
        }

        client.clientID = this.uuid
        client.clientSecret = this.secret
        client.name = this.name
        client.redirectUris = [this.redirect_url]
        await client.save()
    }

    async save() {
        await super.save()

        // Save the associated flitter-auth-compatible client.
        await this.update_auth_client()
    }

    async to_api() {
        return {
            id: this.id,
            name: this.name,
            uuid: this.uuid,
            secret: this.secret,
            api_scopes: this.api_scopes,
            redirect_url: this.redirect_url,
        }
    }

    // See flitter-auth/User
    _array_allow_permission(array_of_permissions, permission) {
        const permission_parts = permission.split(':')

        for ( let i = permission_parts.length; i > 0; i-- ) {
            const permission_string = permission_parts.slice(0, i).join(':')
            if ( array_of_permissions.includes(permission_string) ) return true
        }

        return false
    }

    // See flitter-auth/User
    can(scope){
        return this._array_allow_permission(this.api_scopes, scope)
    }
}

module.exports = exports = ClientModel
