text: /*
  TODO: CloudinaryImageType actally supports 'remove' and 'reset' actions, but
  this field will only submit `""` when 'remove' is clicked. @jossmac we need to
  work out whether we're going to support deleting through the UI.
  */
  
  import React, { PropTypes } from 'react';
  import Field from '../Field';
  import cloudinaryResize from '../../../admin/client/utils/cloudinaryResize';
  import { Button, FormField, FormInput, FormNote } from '../../../admin/client/App/elemental';
  
  import ImageThumbnail from '../../components/ImageThumbnail';
  import FileChangeMessage from '../../components/FileChangeMessage';
  import HiddenFileInput from '../../components/HiddenFileInput';
  import Lightbox from 'react-images';
  
  const SUPPORTED_TYPES = ['image/*', 'application/pdf', 'application/postscript'];
  const SUPPORTED_REGEX = new RegExp(/^image\/|application\/pdf|application\/postscript/g);
  
  let uploadInc = 1000;
  
  const buildInitialState = (props) => ({
  	removeExisting: false,
  	uploadFieldPath: `CloudinaryImage-${props.path}-${++uploadInc}`,
  	userSelectedFile: null,
  });
  
  module.exports = Field.create({
  	propTypes: {
  		collapse: PropTypes.bool,
  		label: PropTypes.string,
  		note: PropTypes.string,
  		path: PropTypes.string.isRequired,
  		value: PropTypes.shape({
  			format: PropTypes.string,
  			height: PropTypes.number,
  			public_id: PropTypes.string,
  			resource_type: PropTypes.string,
  			secure_url: PropTypes.string,
  			signature: PropTypes.string,
  			url: PropTypes.string,
  			version: PropTypes.number,
  			width: PropTypes.number,
  		}),
  	},
  	displayName: 'CloudinaryImageField',
  	statics: {
  		type: 'CloudinaryImage',
  		getDefaultValue: () => ({}),
  	},
  	getInitialState () {
  		return buildInitialState(this.props);
  	},
  	componentWillReceiveProps (nextProps) {
  		// console.log('CloudinaryImageField nextProps:', nextProps);
  	},
  	componentWillUpdate (nextProps) {
  		// Reset the action state when the value changes
  		// TODO: We should add a check for a new item ID in the store
  		if (this.props.value.public_id !== nextProps.value.public_id) {
  			this.setState({
  				removeExisting: false,
  				userSelectedFile: null,
  			});
  		}
  	},
  
  	// ==============================
  	// HELPERS
  	// ==============================
  
  	hasLocal () {
  		return !!this.state.userSelectedFile;
  	},
  	hasExisting () {
  		return !!(this.props.value && this.props.value.url);
  	},
  	hasImage () {
  		return this.hasExisting() || this.hasLocal();
  	},
  	getFilename () {
  		const { format, height, public_id, width } = this.props.value;
  
  		return this.state.userSelectedFile
  			? this.state.userSelectedFile.name
  			: `${public_id}.${format} (${width}×${height})`;
  	},
  	getImageSource (height = 90) {
  		// TODO: This lets really wide images break the layout
  		let src;
  		if (this.hasLocal()) {
  			src = this.state.dataUri;
  		} else if (this.hasExisting()) {
  			src = cloudinaryResize(this.props.value.public_id, {
  				crop: 'fit',
  				height: height,
  				format: 'jpg',
  				secure: this.props.secure,
  			});
  		}
  
  		return src;
  	},
  
  	// ==============================
  	// METHODS
  	// ==============================
  
  	triggerFileBrowser () {
  		this.refs.fileInput.clickDomNode();
  	},
  	handleFileChange (event) {
  		const userSelectedFile = event.target.files[0];
  
  		this.setState({ userSelectedFile });
  	},
  
  	// Toggle the lightbox
  	openLightbox (event) {
  		event.preventDefault();
  		this.setState({
  			lightboxIsVisible: true,
  		});
  	},
  	closeLightbox () {
  		this.setState({
  			lightboxIsVisible: false,
  		});
  	},
  
  	// Handle image selection in file browser
  	handleImageChange (e) {
  		if (!window.FileReader) {
  			// return alert('File reader not supported by browser.');
  			return alert('Этот браузер не поддерживает загрузку файлов.');
  		}
  
  		var reader = new FileReader();
  		var file = e.target.files[0];
  		if (!file) return;
  
  		if (!file.type.match(SUPPORTED_REGEX)) {
  			// return alert('Unsupported file type. Supported formats are: GIF, PNG, JPG, BMP, ICO, PDF, TIFF, EPS, PSD, SVG');
  			return alert('Неподдерживаемый тип файла. Поддерживаются: GIF, PNG, JPG, BMP, ICO, PDF, TIFF, EPS, PSD, SVG');
  		}
  
  		reader.readAsDataURL(file);
  
  		reader.onloadstart = () => {
  			this.setState({
  				loading: true,
  			});
  		};
  		reader.onloadend = (upload) => {
  			this.setState({
  				dataUri: upload.target.result,
  				loading: false,
  				userSelectedFile: file,
  			});
  			this.props.onChange({ file: file });
  		};
  	},
  
  	// If we have a local file added then remove it and reset the file field.
  	handleRemove (e) {
  		var state = {};
  
  		if (this.state.userSelectedFile) {
  			state.userSelectedFile = null;
  		} else if (this.hasExisting()) {
  			state.removeExisting = true;
  		}
  
  		this.setState(state);
  	},
  	undoRemove () {
  		this.setState(buildInitialState(this.props));
  	},
  
  	// ==============================
  	// RENDERERS
  	// ==============================
  
  	renderLightbox () {
  		const { value } = this.props;
  
  		if (!value || !value.public_id) return;
  
  		return (
  			<Lightbox
  				currentImage={0}
  				images={[{ src: this.getImageSource(600) }]}
  				isOpen={this.state.lightboxIsVisible}
  				onClose={this.closeLightbox}
  				showImageCount={false}
  			/>
  		);
  	},
  	renderImagePreview () {
  		const { value } = this.props;
  
  		// render icon feedback for intent
  		let mask;
  		if (this.hasLocal()) mask = 'upload';
  		else if (this.state.removeExisting) mask = 'remove';
  		else if (this.state.loading) mask = 'loading';
  
  		const shouldOpenLightbox = value.format !== 'pdf';
  
  		return (
  			<ImageThumbnail
  				component="a"
  				href={this.getImageSource(600)}
  				onClick={shouldOpenLightbox && this.openLightbox}
  				mask={mask}
  				target="__blank"
  				style={{ float: 'left', marginRight: '1em' }}
  			>
  				<img src={this.getImageSource()} style={{ height: 90 }} />
  			</ImageThumbnail>
  		);
  	},
  	renderFileNameAndOptionalMessage (showChangeMessage = false) {
  		return (
  			<div>
  				{this.hasImage() ? (
  					<FileChangeMessage>
  						{this.getFilename()}
  					</FileChangeMessage>
  				) : null}
  				{showChangeMessage && this.renderChangeMessage()}
  			</div>
  		);
  	},
  	renderChangeMessage () {
  		if (this.state.userSelectedFile) {
  			return (
  				<FileChangeMessage color="success">
  					{/*Save to Upload*/}
  					Нажмите "Сохранить" для загрузки
  				</FileChangeMessage>
  			);
  		} else if (this.state.removeExisting) {
  			return (
  				<FileChangeMessage color="danger">
  					{/*Save to Remove*/}
  					Нажмите "Сохранить" для удаления
  				</FileChangeMessage>
  			);
  		} else {
  			return null;
  		}
  	},
  
  	// Output [cancel/remove/undo] button
  	renderClearButton () {
  		// const clearText = this.hasLocal() ? 'Cancel' : 'Remove Image';
  		const clearText = this.hasLocal() ? 'Отмена' : 'Удалить изображение';
  
  		return this.state.removeExisting ? (
  			<Button variant="link" onClick={this.undoRemove}>
  				{/*Undo Remove*/}
  				Отменить удаление
  			</Button>
  		) : (
  			<Button variant="link" color="cancel" onClick={this.handleRemove}>
  				{clearText}
  			</Button>
  		);
  	},
  
  	renderImageToolbar () {
  		return (
  			<div key={this.props.path + '_toolbar'} className="image-toolbar">
  				<Button onClick={this.triggerFileBrowser}>
  					{/*{this.hasImage() ? 'Change' : 'Upload'} Image*/}
  					{this.hasImage() ? 'Изменить' : 'Загрузить'} изображение
  				</Button>
  				{this.hasImage() ? this.renderClearButton() : null}
  			</div>
  		);
  	},
  
  	renderFileInput () {
  		if (!this.shouldRenderField()) return null;
  
  		return (
  			<HiddenFileInput
  				accept={SUPPORTED_TYPES.join()}
  				ref="fileInput"
  				name={this.state.uploadFieldPath}
  				onChange={this.handleImageChange}
  			/>
  		);
  	},
  
  	// This renders a hidden input that holds the payload data for how the field
  	// should be updated. It should be upload:{filename}, undefined, or 'remove'
  	renderActionInput () {
  		if (!this.shouldRenderField()) return null;
  
  		if (this.state.userSelectedFile || this.state.removeExisting) {
  			let value = '';
  			if (this.state.userSelectedFile) {
  				value = `upload:${this.state.uploadFieldPath}`;
  			} else if (this.state.removeExisting && this.props.autoCleanup) {
  				value = 'delete';
  			}
  			return (
  				<input
  					name={this.getInputName(this.props.path)}
  					type="hidden"
  					value={value}
  				/>
  			);
  		} else {
  			return null;
  		}
  	},
  
  	renderUI () {
  		const { label, note, path } = this.props;
  
  		const imageContainer = (
  			<div style={this.hasImage() ? { marginBottom: '1em' } : null}>
  				{this.hasImage() && this.renderImagePreview()}
  				{this.hasImage() && this.renderFileNameAndOptionalMessage(this.shouldRenderField())}
  			</div>
  		);
  
  		const toolbar = this.shouldRenderField()
  			? this.renderImageToolbar()
  			: <FormInput noedit />;
  
  		return (
  			<FormField label={label} className="field-type-cloudinaryimage" htmlFor={path}>
  				{imageContainer}
  				{toolbar}
  				{!!note && <FormNote note={note} />}
  				{this.renderLightbox()}
  				{this.renderFileInput()}
  				{this.renderActionInput()}
  			</FormField>
  		);
  	},
  });
  