'use strict';

Object.defineProperty(exports, "__esModule", {
	value: true
});

var _objectWithoutProperties2 = require('babel-runtime/helpers/objectWithoutProperties');

var _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2);

var _extends2 = require('babel-runtime/helpers/extends');

var _extends3 = _interopRequireDefault(_extends2);

var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of');

var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf);

var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');

var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);

var _createClass2 = require('babel-runtime/helpers/createClass');

var _createClass3 = _interopRequireDefault(_createClass2);

var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');

var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);

var _inherits2 = require('babel-runtime/helpers/inherits');

var _inherits3 = _interopRequireDefault(_inherits2);

var _slicedToArray2 = require('babel-runtime/helpers/slicedToArray');

var _slicedToArray3 = _interopRequireDefault(_slicedToArray2);

var _react = require('react');

var _react2 = _interopRequireDefault(_react);

var _reactDom = require('react-dom');

var _reactDom2 = _interopRequireDefault(_reactDom);

var _libphonenumberJs = require('libphonenumber-js');

var _inputFormat = require('input-format');

var _classnames = require('classnames');

var _classnames2 = _interopRequireDefault(_classnames);

var _reactResponsiveUi = require('./react-responsive-ui');

var _countryNames = require('./country names');

var _countryNames2 = _interopRequireDefault(_countryNames);

var _internationalIcon = require('./international icon');

var _internationalIcon2 = _interopRequireDefault(_internationalIcon);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

// Generate default country options list
var country_options = _countryNames2.default.map(function (_ref) {
	var _ref2 = (0, _slicedToArray3.default)(_ref, 2);

	var value = _ref2[0];
	var label = _ref2[1];
	return {
		value: value.toUpperCase(),
		label: label
	};
});

// Not importing here directly from `react-responsive-ui` npm package
// just to reduce the overall bundle size.

var Input = function (_Component) {
	(0, _inherits3.default)(Input, _Component);

	function Input(props) {
		(0, _classCallCheck3.default)(this, Input);

		var _this = (0, _possibleConstructorReturn3.default)(this, (Input.__proto__ || (0, _getPrototypeOf2.default)(Input)).call(this, props));

		_this.state = {};
		var countries = props.countries;
		var country = props.country;

		// Clone the array to avoid mutating properties being passed in

		countries = countries.slice();

		// Add the "International" option to the list of countries
		var add_international_option = true;

		// If an array of country codes is passed
		// then limit the available countries to only those ones specified
		// (also excluding the "International" option from the list)
		if (typeof countries[0] === 'string') {
			// If the passed `country` is not in the `countries` list,
			// then just select the first one.
			if (countries.indexOf(country) === -1) {
				country = countries[0];
			}

			// Generate country options
			countries = _countryNames2.default.filter(function (_ref3) {
				var _ref4 = (0, _slicedToArray3.default)(_ref3, 2);

				var value = _ref4[0];
				var label = _ref4[1];

				return countries.indexOf(value.toUpperCase()) !== -1;
			}).map(function (_ref5) {
				var _ref6 = (0, _slicedToArray3.default)(_ref5, 2);

				var value = _ref6[0];
				var label = _ref6[1];
				return {
					value: value.toUpperCase(),
					label: label,
					icon: get_country_option_icon(value.toUpperCase(), props)
				};
			});

			// No "International" option is needed here
			add_international_option = false;
		}

		// If the default country is set, then populate it
		_this.state.country_code = country;

		var value = props.value;
		var lockCountry = props.lockCountry;
		var dictionary = props.dictionary;
		var internationalIcon = props.internationalIcon;


		if (value) {
			_this.state.value = _this.correct_initial_value_if_neccessary(value, country);
		}

		// Sanity check
		if (lockCountry && !country) {
			throw new Error('You must specify a `country` when using `lockCountry` mode');
		}

		// Set country option icons (national flags)
		// for those option list items
		// which don't have an icon set.
		// (in case of user-supplied `countries` prop)
		var i = 0;
		while (i < countries.length) {
			var country_option = countries[i];

			// Makes sure an `icon` is set for each country option
			if (!country_option.icon) {
				// Avoid mutating the original property
				country_option = (0, _extends3.default)({}, country_option);
				// Set the icon
				var country_code = country_option.value.toLowerCase();
				country_option.icon = get_country_option_icon(country_code, props);
				// Update the country option in the list of options
				countries[i] = country_option;
			}

			i++;
		}

		// `<select/>` `<option/>`s
		_this.select_options = [];

		// The default behaviour is to add the
		// "International" option to the country list
		if (add_international_option) {
			_this.select_options.push({
				value: '-',
				label: dictionary.International || 'International',
				icon: internationalIcon
			});
		}

		_this.select_options = _this.select_options.concat(countries);

		_this.on_key_down = _this.on_key_down.bind(_this);
		_this.on_change = _this.on_change.bind(_this);
		_this.set_country = _this.set_country.bind(_this);
		_this.parse = _this.parse.bind(_this);
		_this.format = _this.format.bind(_this);

		_this.country_select_toggled = _this.country_select_toggled.bind(_this);
		_this.on_country_select_tab_out = _this.on_country_select_tab_out.bind(_this);
		return _this;
	}

	// If the country code is specified
	//   If the value has a leading plus sign
	//     If it converts into a valid national number for this country
	//       Then the value is set to be that national number
	//     Else
	//       The leading + sign is trimmed
	//   Else
	//     The value stays as it is
	// Else
	//   If the value has a leading + sign
	//     The value stays as it is
	//   Else
	//     The + sign is prepended
	//


	(0, _createClass3.default)(Input, [{
		key: 'correct_initial_value_if_neccessary',
		value: function correct_initial_value_if_neccessary(value, country_code) {
			if (!value) {
				return;
			}

			// If the country code is specified
			if (country_code) {
				// If the value has a leading plus sign
				if (value[0] === '+') {
					// If it's a fully-entered phone number
					// that converts into a valid national number for this country
					// then the value is set to be that national number.

					var parsed = (0, _libphonenumberJs.parse)(value);

					if (parsed.country === country_code) {
						return this.format(parsed.phone, country_code).text;
					}

					// Else the leading + sign is trimmed.
					return value.slice(1);
				}

				// Else the value stays as it is
				return value;
			}

			// The country is not set.
			// Assuming that's an international phone number.

			// If the value has a leading + sign
			if (value[0] === '+') {
				// The value is correct
				return value;
			}

			// The + sign is prepended
			return '+' + value;
		}
	}, {
		key: 'set_country_code_value',
		value: function set_country_code_value(country_code) {
			var onCountryChange = this.props.onCountryChange;


			if (onCountryChange) {
				onCountryChange(country_code);
			}

			this.setState({ country_code: country_code });
		}

		// `<select/>` `onChange` handler

	}, {
		key: 'set_country',
		value: function set_country(country_code) {
			var _this2 = this;

			// Previously selected country
			var previous_country_code = this.state.country_code;

			if (country_code === '-') {
				country_code = undefined;
			}

			this.set_country_code_value(country_code);

			// Adjust the phone number (`value`)
			// according to the selected `country_code`

			var value = this.state.value;

			// If switching to a country from International
			//   If the international number belongs to this country
			//     Convert it to a national number
			//   Else
			//     Trim the leading + sign
			//
			// If switching to a country from a country
			//   If the value has a leading + sign
			//     If the international number belongs to this country
			//       Convert it to a national number
			//     Else
			//       Trim the leading + sign
			//   Else
			//     The value stays as it is
			//
			// If switching to International from a country
			//   If the value has a leading + sign
			//     The value stays as it is
			//   Else
			//     Take the international plaintext value

			if (value) {
				// If switching to a country from International
				if (!previous_country_code && country_code) {
					// The value is international plaintext
					var parsed = (0, _libphonenumberJs.parse)(value);

					// If it's for this country,
					// then convert it to a national number
					if (parsed.country === country_code) {
						value = this.format(parsed.phone, country_code).text;
					}
					// Else just trim the + sign
					else {
							value = value.slice(1);
						}
				}

				if (previous_country_code && country_code) {
					if (value[0] === '+') {
						var _parsed = (0, _libphonenumberJs.parse)(value);

						if (_parsed.country === country_code) {
							value = this.format(_parsed.phone, country_code).text;
						} else {
							value = value.slice(1);
						}
					}
				}

				// If switching to International from a country
				if (previous_country_code && !country_code) {
					// If no leading + sign
					if (value[0] !== '+') {
						// Take the international plaintext value
						value = (0, _libphonenumberJs.format)(parse_partial_number(value, previous_country_code).national_number, previous_country_code, 'International_plaintext');
					}
				}

				// Update the adjusted `value`
				// and update `this.props.value` (in e.164 phone number format)
				// according to the new `this.state.value`.
				// (keep them in sync)
				this.on_change(value, country_code);
			}

			// Focus the phone number input upon country selection
			// (do it in a timeout because the `<input/>`
			//  is hidden while selecting a country)
			setTimeout(function () {
				return _reactDom2.default.findDOMNode(_this2.input).focus();
			}, 0);
		}

		// `input-format` `parse` character function
		// https://github.com/halt-hammerzeit/input-format

	}, {
		key: 'parse',
		value: function parse(character, value) {
			var _props = this.props;
			var lockCountry = _props.lockCountry;
			var countries = _props.countries;


			if (character === '+') {
				// Only leading '+' is allowed
				// (if `country` is not locked, or if `countries`
				//  are not limited to a specific set of country codes)
				if (!lockCountry && typeof countries[0] !== 'string' && !value) {
					return character;
				}
			}
			// Allow digits
			else if (character >= '0' && character <= '9') {
					return character;
				}
		}

		// `input-format` `format` function
		// https://github.com/halt-hammerzeit/input-format

	}, {
		key: 'format',
		value: function format(value) {
			var country_code = arguments.length <= 1 || arguments[1] === undefined ? this.state.country_code : arguments[1];

			// `value` is already parsed input, i.e.
			// either International plaintext phone number
			// or just local phone number digits.

			// "As you type" formatter
			var formatter = new _libphonenumberJs.as_you_type(country_code);

			// Is used to check if a country code can already be derived
			this.formatter = formatter;

			// Format phone number
			var text = formatter.input(value);

			return { text: text, template: formatter.template };
		}

		// `<input/>` `onKeyDown` handler

	}, {
		key: 'on_key_down',
		value: function on_key_down(event) {
			// Expand country `<select/>`` on "Down arrow" key press
			if (event.keyCode === 40) {
				this.select.toggle();
			}
		}

		// `<input/>` `onChange` handler.
		// Updates `this.props.value` (in e.164 phone number format)
		// according to the new `this.state.value`.
		// (keeps them in sync)

	}, {
		key: 'on_change',
		value: function on_change(value) {
			var country_code = arguments.length <= 1 || arguments[1] === undefined ? this.state.country_code : arguments[1];
			var onChange = this.props.onChange;

			// If the `<input/>` is empty then just exit

			if (!value) {
				this.setState({ value: value });
				return onChange(value);
			}

			// If a phone number is being input as an international one
			// and the country code can already be derived,
			// then switch the country.
			// (`001` is a special "non-geograpical entity" code in `libphonenumber` library)
			if (value[0] === '+' && this.formatter.country && this.formatter.country !== '001') {
				country_code = this.formatter.country;
				this.set_country_code_value(country_code);
			}

			// If "International" mode is selected
			// and the `value` doesn't start with a + sign,
			// then prepend it to the `value`.
			if (value[0] !== '+' && !country_code) {
				value = '+' + value;
			}

			// Convert `value` to E.164 phone number format
			// and write it to `this.props.value`.
			onChange(e164(value, country_code));

			// Update the `value`
			this.setState({ value: value });
		}

		// When country `<select/>` is toggled

	}, {
		key: 'country_select_toggled',
		value: function country_select_toggled(is_shown) {
			this.setState({ country_select_is_shown: is_shown });
		}

		// Focuses the `<input/>` field
		// on tab out of the country `<select/>`

	}, {
		key: 'on_country_select_tab_out',
		value: function on_country_select_tab_out(event) {
			var _this3 = this;

			event.preventDefault();

			// Focus the phone number input upon country selection
			// (do it in a timeout because the `<input/>`
			//  is hidden while selecting a country)
			setTimeout(function () {
				return _reactDom2.default.findDOMNode(_this3.input).focus();
			}, 0);
		}

		// Listen for default country property:
		// if it is set after the page loads
		// and the user hasn't selected a country yet
		// then select the default country.

	}, {
		key: 'componentWillReceiveProps',
		value: function componentWillReceiveProps(new_props) {
			var _props2 = this.props;
			var countries = _props2.countries;
			var country = _props2.country;
			var value = _props2.value;

			// If the default country changed
			// (e.g. in case of IP detection)

			if (new_props.country !== country) {
				// If the phone number input field is currently empty
				// (e.g. not touched yet) then change the selected `country`
				// to the newly passed one (e.g. as a result of a GeoIP query)
				if (!value) {
					// If the passed `country` is not in the `countries` list,
					// then don't update the `country`.
					if (typeof countries[0] === 'string' && countries.indexOf(new_props.country) === -1) {
						// Don't update the `country`
					} else {
						// Set the new `country`
						this.set_country(new_props.country);
					}
				}
			}
		}
	}, {
		key: 'render',
		value: function render() {
			var _this4 = this;

			var _props3 = this.props;
			var dictionary = _props3.dictionary;
			var countries = _props3.countries;
			var saveOnIcons = _props3.saveOnIcons;
			var internationalIcon = _props3.internationalIcon;
			var country = _props3.country;
			var lockCountry = _props3.lockCountry;
			var onCountryChange = _props3.onCountryChange;
			var flagsPath = _props3.flagsPath;
			var disabled = _props3.disabled;
			var style = _props3.style;
			var className = _props3.className;
			var input_props = (0, _objectWithoutProperties3.default)(_props3, ['dictionary', 'countries', 'saveOnIcons', 'internationalIcon', 'country', 'lockCountry', 'onCountryChange', 'flagsPath', 'disabled', 'style', 'className']);
			var country_select_is_shown = this.state.country_select_is_shown;


			var markup = _react2.default.createElement(
				'div',
				{ style: style, className: (0, _classnames2.default)('react-phone-number-input', className, {
						'react-phone-number-input--valid': this.formatter && this.formatter.valid
					}) },
				!lockCountry && _react2.default.createElement(_reactResponsiveUi.Select, {
					ref: function ref(_ref7) {
						return _this4.select = _ref7;
					},
					value: this.state.country_code || '-',
					options: this.select_options,
					onChange: this.set_country,
					disabled: disabled,
					onToggle: this.country_select_toggled,
					onTabOut: this.on_country_select_tab_out,
					autocomplete: true,
					concise: true,
					focusUponSelection: false,
					saveOnIcons: saveOnIcons,
					name: input_props.name ? input_props.name + '__country' : undefined,
					className: 'react-phone-number-input__country',
					style: select_style }),
				!country_select_is_shown && _react2.default.createElement(_inputFormat.ReactInput, (0, _extends3.default)({}, input_props, {
					ref: function ref(_ref8) {
						return _this4.input = _ref8;
					},
					value: this.state.value,
					onChange: this.on_change,
					disabled: disabled,
					type: 'tel',
					parse: this.parse,
					format: this.format,
					onKeyDown: this.on_key_down,
					className: (0, _classnames2.default)('react-phone-number-input__phone', {
						'react-phone-number-input__phone--valid': this.formatter && this.formatter.valid
					}),
					style: input_style }))
			);

			return markup;
		}
	}]);
	return Input;
}(_react.Component);

// Parses a partially entered phone number
// and returns the national number so far.
// Not using `libphonenumber-js`'s `parse`
// function here because `parse` only works
// when the number is fully entered,
// and this one is for partially entered number.


Input.propTypes = {
	// Phone number `value`.
	// Is a plaintext international phone number
	// (e.g. "+12223333333" for USA)
	value: _react.PropTypes.string,

	// This handler is called each time
	// the phone number <input/> changes its textual value.
	onChange: _react.PropTypes.func.isRequired,

	// This `onBlur` interceptor is a workaround for `redux-form`,
	// so that it gets a parsed `value` in its `onBlur` handler,
	// not the formatted one.
	// (`redux-form` passed `onBlur` to this component
	//  and this component intercepts that `onBlur`
	//  to make sure it works correctly with `redux-form`)
	onBlur: _react.PropTypes.func,

	// Disables both the <input/> and the <select/>
	// (is `false` by default)
	disabled: _react.PropTypes.bool.isRequired,

	// Two-letter country code
	// to be used as the default country
	// for local (non-international) phone numbers.
	country: _react.PropTypes.string,

	// If the country is locked then
	// the country `<Select/>` won't be rendered
	// and the phone country will always stay the same.
	// This will also prohibit inputting phone numbers
	// in international format ("+...").
	// (is `false` by default)
	lockCountry: _react.PropTypes.bool.isRequired,

	// Is called when the selected country changes
	// (either by a user manually, or by autoparsing
	//  an international phone number being input).
	// This handler does not need to update the `country` property.
	// It's simply a listener for those who might need that for whatever purpose.
	onCountryChange: _react.PropTypes.func,

	// Localization dictionary:
	// `{ International: 'Международный', RU: 'Россия', US: 'США', ... }`
	dictionary: _react.PropTypes.objectOf(_react.PropTypes.string),

	// A custom selectable options list.
	// May be used to show all country flags in the <select/> list.
	//
	// Example:
	//
	// SVG flags for all countries (3 MegaBytes in size).
	// Too big for the public internet, but may be suitable
	// for enterprise software (e.g. CRM systems).
	// import countriesWithFlags from 'react-phone-number-input/countries-with-flags'
	//
	// <Phone ... countries={countriesWithFlags}/>
	//
	// (and that should be working)
	//
	countries: _react.PropTypes.oneOfType([
	// Either a list of customized `<Select/>` options
	_react.PropTypes.arrayOf(_react.PropTypes.shape({
		// Option value
		value: _react2.default.PropTypes.string.isRequired,
		// Option label
		label: _react2.default.PropTypes.string.isRequired,
		// Option icon
		icon: _react2.default.PropTypes.element
	})),
	// Or just a list of possible countries
	_react.PropTypes.arrayOf(_react.PropTypes.string)]).isRequired,

	// Custom national flag icons
	flags: _react.PropTypes.objectOf(_react2.default.PropTypes.element),

	// If set to `false`, then country flags will be shown
	// for all countries in the options list
	// (not just for selected country).
	saveOnIcons: _react.PropTypes.bool.isRequired,

	// Custom "International" phone number type icon.
	internationalIcon: _react.PropTypes.element.isRequired,

	// A base URL path for national flag SVG icons.
	// By default it uses the ones from `flag-icon-css` github repo.
	flagsPath: _react.PropTypes.string.isRequired,

	// CSS style object
	style: _react.PropTypes.object,

	// CSS class
	className: _react.PropTypes.string
};
Input.defaultProps = {
	// Is enabled
	disabled: false,

	// By default use the ones from `flag-icon-css` github repo.
	flagsPath: 'https://lipis.github.io/flag-icon-css/flags/4x3/',

	// Default international icon (globe)
	internationalIcon: _react2.default.createElement(
		'div',
		{ className: 'react-phone-number-input__icon react-phone-number-input__icon--international' },
		_react2.default.createElement(_internationalIcon2.default, null)
	),

	// Default country labels
	countries: country_options,

	// Custom country names
	dictionary: {},

	// Don't show flags for all countries in the options list
	// (show it just for selected country).
	// (to save user's traffic because all flags are about 3 MegaBytes)
	saveOnIcons: true,

	lockCountry: false
};
exports.default = Input;
function parse_partial_number(value, country_code) {
	// "As you type" formatter
	var formatter = new _libphonenumberJs.as_you_type(country_code);

	// Input partially entered phone number
	formatter.input(value);

	// Return the parsed partial phone number
	// (has `.national_number`, `.country`, etc)
	return formatter;
}

// Coverts `value` to E.164 phone number format
function e164(value, country_code) {
	// If the phone number is being input in a country-specific format
	//   If the value has a leading + sign
	//     The value stays as it is
	//   Else
	//     The value is converted to international plaintext
	// Else, the phone number is being input in an international format
	//   If the value has a leading + sign
	//     The value stays as it is
	//   Else
	//     The value is prepended with a + sign

	if (country_code) {
		if (value[0] === '+') {
			return value;
		}

		var partial_national_number = parse_partial_number(value, country_code).national_number;
		return (0, _libphonenumberJs.format)(partial_national_number, country_code, 'International_plaintext');
	}

	if (value[0] === '+') {
		return value;
	}

	return '+' + value;
}

var select_style = {
	display: 'inline-block',
	verticalAlign: 'bottom'
};

var input_style = select_style;

function get_country_option_icon(country_code, _ref9) {
	var flags = _ref9.flags;
	var flagsPath = _ref9.flagsPath;

	if (flags && flags[country_code]) {
		return flags[country_code];
	}

	return _react2.default.createElement('img', { className: 'react-phone-number-input__icon', src: '' + flagsPath + country_code.toLowerCase() + '.svg' });
}
//# sourceMappingURL=input.js.map