'use strict';

const Assert = require('@hapi/hoek/assert');

const Base = require('../base');
const Common = require('../common');


const internals = {};


module.exports = Base._extend({

    type: 'any',

    flags: {

        only: { default: false }
    },

    terms: {

        alterations: { init: null },
        examples: { init: null },
        metas: { init: [] },
        notes: { init: [] },
        shared: { init: null },
        tags: { init: [] },
        whens: { init: null }
    },

    rules: {

        custom: {
            method(method, description) {

                Assert(typeof method === 'function', 'Method must be a function');
                Assert(description === undefined || description && typeof description === 'string', 'Description must be a non-empty string');

                return this.$_addRule({ name: 'custom', args: { method, description } });
            },
            validate(value, helpers, { method }) {

                try {
                    return method(value, helpers);
                }
                catch (err) {
                    return helpers.error('any.custom', { error: err });
                }
            },
            args: ['method', 'description'],
            multi: true
        },

        messages: {
            method(messages) {

                return this.prefs({ messages });
            }
        },

        shared: {
            method(schema) {

                Assert(Common.isSchema(schema) && schema._flags.id, 'Schema must be a schema with an id');

                const obj = this.clone();
                obj.$_terms.shared = obj.$_terms.shared || [];
                obj.$_terms.shared.push(schema);
                obj.$_mutateRegister(schema);
                return obj;
            }
        }
    },

    messages: {
        'any.custom': '{{#label}} failed custom validation because {{#error.message}}',
        'any.default': '{{#label}} threw an error when running default method',
        'any.failover': '{{#label}} threw an error when running failover method',
        'any.invalid': '{{#label}} contains an invalid value',
        'any.only': '{{#label}} must be one of {{#valids}}',
        'any.ref': '{{#label}} {{#arg}} references {{:#ref}} which {{#reason}}',
        'any.required': '{{#label}} is required',
        'any.unknown': '{{#label}} is not allowed'
    }
});
