# Source: crop-to-box.js

    const hasard = require('hasard');
    const CropAugmenter = require('./crop');

    /**
    * Crop the image considering input's "boxes" parameter and with
    * a variation given by sigma
    *
    * @param {Object} opts options
    * @param {NumberArgument} [opts.cornersVariation] length-2 x lenght-2 variate (in percent) of box
    * ex : [[x1, y1], [x2, y2]] will cropp a box of size (x1+x2 +1)*width x (y1+y2 +1)*height
    * Positive numbers will increase the size of the box
    * @param {NumberArgument} opts.sigma sigma af a normal distribution of cornersVariation
    * @param {NumberArgument} opts.mean mean of a normal distribution of cornersVariation
    * @param {NumberArgument} [opts.boxIndex] index of the box to use, by default, will be randomly decided
    * @example
    // Simple usage, will crop a random box among boxes,
    // and return it as the new image
    // will throw an error if no boxes
    const cropper = ia.cropToBox();
    * @example
    // default parameter is sigma, here 10% variation
    ia.cropToBox(0.1);
    * @example
    // here 20% variation, in the normal distribution
    // and by average width of the cropped box will be 20% larger (10% + 10%) and same for height
    ia.cropToBox({sigma: 0.2, mean: 0.1});
    */

    class CropToBoxAugmenter extends CropAugmenter {
    	constructor(opts, ia) {
    		let o;
    		if (typeof (opts) === 'number' || hasard.isHasard(opts)) {
    			o = {sigma: opts};
    		} else {
    			o = opts;
    		}

    		super(o, ia);
    		const {sigma, mean = 0, boxIndex, cornersVariation} = o;

    		this.sigma = this.toSize2(sigma);
    		this.mean = this.toSize2(mean);
    		this.cornersVariation = cornersVariation;
    		this.boxIndex = boxIndex;
    	}

    	buildParams({boxes}) {
    		return new hasard.Object({
    			cornersVariation: this.cornersVariation || hasard.array({
    				size: 2,
    				value: new hasard.Array([
    					new hasard.Number({
    						type: 'normal',
    						mean: hasard.getProperty(0, this.mean),
    						std: hasard.getProperty(0, this.sigma)
    					}),
    					new hasard.Number({
    						type: 'normal',
    						mean: hasard.getProperty(1, this.mean),
    						std: hasard.getProperty(1, this.sigma)
    					})
    				])
    			}),
    			box: hasard.getProperty(this.boxIndex || hasard.integer(0, boxes.length - 1), boxes)
    		});
    	}

    	checkParams() {
    		// Override
    	}

    	getRect({width, height, params}) {
    		const {cornersVariation} = params;
    		const {box} = params;
    		const x = Math.round(Math.max(0, box[0] - (cornersVariation[0][0] * box[2])));
    		const y = Math.round(Math.max(0, box[1] - (cornersVariation[0][1] * box[3])));
    		const w = Math.round(Math.min(width - x, box[2] + ((cornersVariation[0][0] + cornersVariation[1][0]) * box[2])));
    		const h = Math.round(Math.min(height - y, box[3] + ((cornersVariation[0][1] + cornersVariation[1][1]) * box[3])));

    		return {
    			x,
    			y,
    			w,
    			h
    		};
    	}
    }

    module.exports = CropToBoxAugmenter;