(function() {

	'use strict';



	var L = require('leaflet');



	var Localization = require('./localization');



	module.exports = L.Class.extend({

		options: {

			units: 'metric',

			unitNames: null,

			language: 'en',

			roundingSensitivity: 1,

			distanceTemplate: '{value} {unit}'

		},



		initialize: function(options) {

			L.setOptions(this, options);



			var langs = L.Util.isArray(this.options.language) ?

				this.options.language :

				[this.options.language, 'en'];

			this._localization = new Localization(langs);

		},



		formatDistance: function(d /* Number (meters) */, sensitivity) {

			var un = this.options.unitNames || this._localization.localize('units'),

				simpleRounding = sensitivity <= 0,

				round = simpleRounding ? function(v) { return v; } : L.bind(this._round, this),

			    v,

			    yards,

				data,

				pow10;



			if (this.options.units === 'imperial') {

				yards = d / 0.9144;

				if (yards >= 1000) {

					data = {

						value: round(d / 1609.344, sensitivity),

						unit: un.miles

					};

				} else {

					data = {

						value: round(yards, sensitivity),

						unit: un.yards

					};

				}

			} else {

				v = round(d, sensitivity);

				data = {

					value: v >= 1000 ? (v / 1000) : v,

					unit: v >= 1000 ? un.kilometers : un.meters

				};

			}



			if (simpleRounding) {

				data.value = data.value.toFixed(-sensitivity);

			}



			return L.Util.template(this.options.distanceTemplate, data);

		},



		_round: function(d, sensitivity) {

			var s = sensitivity || this.options.roundingSensitivity,

				pow10 = Math.pow(10, (Math.floor(d / s) + '').length - 1),

				r = Math.floor(d / pow10),

				p = (r > 5) ? pow10 : pow10 / 2;



			return Math.round(d / p) * p;

		},



		formatTime: function(t /* Number (seconds) */) {

			var un = this.options.unitNames || this._localization.localize('units');

			// More than 30 seconds precision looks ridiculous

			t = Math.round(t / 30) * 30;



			if (t > 86400) {

				return Math.round(t / 3600) + ' ' + un.hours;

			} else if (t > 3600) {

				return Math.floor(t / 3600) + ' ' + un.hours + ' ' +

					Math.round((t % 3600) / 60) + ' ' + un.minutes;

			} else if (t > 300) {

				return Math.round(t / 60) + ' ' + un.minutes;

			} else if (t > 60) {

				return Math.floor(t / 60) + ' ' + un.minutes +

					(t % 60 !== 0 ? ' ' + (t % 60) + ' ' + un.seconds : '');

			} else {

				return t + ' ' + un.seconds;

			}

		},



		formatInstruction: function(instr, i) {

			if (instr.text === undefined) {

				return this.capitalize(L.Util.template(this._getInstructionTemplate(instr, i),

					L.extend({}, instr, {

						exitStr: instr.exit ? this._localization.localize('formatOrder')(instr.exit) : '',

						dir: this._localization.localize(['directions', instr.direction]),

						modifier: this._localization.localize(['directions', instr.modifier])

					})));

			} else {

				return instr.text;

			}

		},



		getIconName: function(instr, i) {

			switch (instr.type) {

			case 'Head':

				if (i === 0) {

					return 'depart';

				}

				break;

			case 'WaypointReached':

				return 'via';

			case 'Roundabout':

				return 'enter-roundabout';

			case 'DestinationReached':

				return 'arrive';

			}



			switch (instr.modifier) {

			case 'Straight':

				return 'continue';

			case 'SlightRight':

				return 'bear-right';

			case 'Right':

				return 'turn-right';

			case 'SharpRight':

				return 'sharp-right';

			case 'TurnAround':

			case 'Uturn':

				return 'u-turn';

			case 'SharpLeft':

				return 'sharp-left';

			case 'Left':

				return 'turn-left';

			case 'SlightLeft':

				return 'bear-left';

			}

		},



		capitalize: function(s) {

			return s.charAt(0).toUpperCase() + s.substring(1);

		},



		_getInstructionTemplate: function(instr, i) {

			var type = instr.type === 'Straight' ? (i === 0 ? 'Head' : 'Continue') : instr.type,

				strings = this._localization.localize(['instructions', type]);



			if (!strings) {

				strings = [

					this._localization.localize(['directions', type]),

					' ' + this._localization.localize(['instructions', 'Onto'])

				];

			}



			return strings[0] + (strings.length > 1 && instr.road ? strings[1] : '');

		}

	});

})();

