// @flow
import validate from './validate/validate.js';
import latestStyleSpec from './reference/latest.js';
import validateGlyphsURL from './validate/validate_glyphs_url.js';

import _validateSource from './validate/validate_source.js';
import _validateLight from './validate/validate_light.js';
import _validateTerrain from './validate/validate_terrain.js';
import _validateFog from './validate/validate_fog.js';
import _validateLayer from './validate/validate_layer.js';
import _validateFilter from './validate/validate_filter.js';
import _validatePaintProperty from './validate/validate_paint_property.js';
import _validateLayoutProperty from './validate/validate_layout_property.js';

import type {StyleSpecification} from './types.js';

export type ValidationError = {
    message: string;
    identifier?: ?string;
    line?: ?number;
};
export type ValidationErrors = $ReadOnlyArray<ValidationError>;
export type Validator = (Object) => ValidationErrors;

/**
 * Validate a Mapbox GL style against the style specification. This entrypoint,
 * `mapbox-gl-style-spec/lib/validate_style.min`, is designed to produce as
 * small a browserify bundle as possible by omitting unnecessary functionality
 * and legacy style specifications.
 *
 * @private
 * @param {Object} style The style to be validated.
 * @param {Object} [styleSpec] The style specification to validate against.
 *     If omitted, the latest style spec is used.
 * @returns {Array<ValidationError>}
 * @example
 *   var validate = require('mapbox-gl-style-spec/lib/validate_style.min');
 *   var errors = validate(style);
 */
export function validateStyle(style: StyleSpecification, styleSpec: Object = latestStyleSpec): ValidationErrors {

    const errors = validate({
        key: '',
        value: style,
        valueSpec: styleSpec.$root,
        styleSpec,
        style,
        objectElementValidators: {
            glyphs: validateGlyphsURL,
            '*': () => []
        }
    });
    return sortErrors(errors);
}

export const validateSource: Validator = opts => sortErrors(_validateSource(opts));
export const validateLight: Validator = opts => sortErrors(_validateLight(opts));
export const validateTerrain: Validator = opts => sortErrors(_validateTerrain(opts));
export const validateFog: Validator = opts => sortErrors(_validateFog(opts));
export const validateLayer: Validator = opts => sortErrors(_validateLayer(opts));
export const validateFilter: Validator = opts => sortErrors(_validateFilter(opts));
export const validatePaintProperty: Validator = opts => sortErrors(_validatePaintProperty(opts));
export const validateLayoutProperty: Validator = opts => sortErrors(_validateLayoutProperty(opts));

function sortErrors(errors) {
    return errors.slice().sort((a, b) => a.line && b.line ? a.line - b.line : 0);
}