/* cfb-editor (C) 2017-present  SheetJS -- http://sheetjs.com */
/* eslint-env browser */
import React, { PureComponent } from 'react';
import { easyComp } from 'react-easy-state';
import { Link, Redirect } from 'react-router-dom';
import { Icon } from 'react-fa';
import SyntaxHighlighter from 'react-syntax-highlighter';
import { arduinoLight } from 'react-syntax-highlighter/styles/hljs';
import * as Spinner from 'react-spinkit';
import './MainPane.css';

import { sprintf } from 'printj';
import { buf } from 'crc-32';

import store from '../state';
import DataInput from '../components/DataInput';
import { line, fix_string, decode_msi_name } from '../utils/misc';
import { THRESH } from '../consts';
import xml from '../utils/xml';

/* TODO: load through state so screen doesn't block on render */
class FileView extends PureComponent {
	constructor(props) {
		super(props);
		this.state = {loading: true, FN:"", _size:0, _crc32:"", show_text:false, indexData:[]};
		["export", "delete", "rename", "handle", "stload", "common"].forEach(n => { this[n] = this[n].bind(this); });
	}
	componentWillMount() { this.common(this.props, true); }
	componentWillReceiveProps(nextProps) { this.common(nextProps, false); return true; }
	export() { store.exportBStrById(this.props.idx); }
	delete() { this.props.deleteEntry(this.props.idx); }
	rename() { this.props.renameEntry(this.props.idx); }
	handle(f) { this.props.handleFile(this.props.idx, f); }
	stload() { }
	common(props/*, mnt*/) {
		if(!this.state.loading) { this.setState({loading:true}); }
		//const doit = mnt || this.props.idx != props.idx || this.props.mode != props.mode;
		setTimeout(() => {
			const FP = store.getFileNameById(props.idx), FI = store.getFileEntryById(props.idx);
			if(!FP || !FI || store.isCFB() && FI.type != 2) return this.setState({loading:false});
			const FN = fix_string(FI.name);

			const content = store.getContentByEntry(FI);
			const _size = store.getSizeByEntry(FI);
			const _crc32 = sprintf("%0.8X", buf(content));

			const show_text = props.mode == "text";
			const T = show_text ? store.getTextByEntry(FI) : "";
			const doxml = T && (T.slice(0,6) == "<?xml " || T.slice(0,100).match(/^<\w*(:\w+)?[\s/>]/));

			let show_link = props.mode || "text"; if(show_link == "full") show_link = "text";
			if(!props.mode || props.mode == "full") {
				const hdr = store.getContentSliceByEntry(FI,0,16);
				if(hdr[0] == 0xFF && hdr[1] == 0xD8 && hdr[2] == 0xFF) show_link = "imag";
				if(hdr[0] == 0x89 && hdr[1] == 0x50 && hdr[2] == 0x4E) show_link = "imag";
				if(hdr[0] == 0x47 && hdr[1] == 0x49 && hdr[2] == 0x46 && hdr[3] == 0x38) show_link = "imag";
			}

			const show_imag = this.props.mode == "imag", I = show_imag ? "data:image/jpeg;base64," + btoa(store.getTextByEntry(FI)) : "";

			const Target = this.props && this.props.mode ? store.getSizeByEntry(FI) : Math.min(store.getSizeByEntry(FI),THRESH);
			const indices = Array.from({length:(Target)+15>>4}).map((x,i) => 16*i);
			const indexData = (T || I) ? [] : indices.map(x => line([x, store.getContentSliceByEntry(FI, x,x+16)]));
			this.setState({ loading:false, FN, _size, _crc32, show_text, T, doxml, show_link, show_imag, I, indices, indexData });
			this.forceUpdate();
		}, 0);
	}
	render() {
		const FP = store.getFileNameById(this.props.idx), FI = store.getFileEntryById(this.props.idx);
		if(!FP || !FI || store.isCFB() && FI.type != 2) return ( <Redirect to={`/`} /> );

		const _FP = fix_string(FP);

		/* indices, indices.map(x => line([x, store.getContentSliceByEntry(FI, x,x+16)])) */
		const { FN, _size, _crc32, show_text, T, doxml, show_link, show_imag, I, indices, indexData } = this.state;
		const partial = _size > THRESH && !this.props.mode;

		const show_link_txt = { "text": "Text", "imag": "Image" }[show_link];
		const out = (
<div className="conpainer">
	<div><b>File Name:</b> {FN} {FN.charCodeAt(0) >= 0x3800 && FN.charCodeAt(0) <= 0x4840 && `MSI Name: ${decode_msi_name(FN)}`}</div>
	<div className="minor">{FN != FI.name ? `File name has non-display characters, which are rendered as "\\u" followed by character code` : `\u00A0`}</div>
	<div className="minor">&nbsp;</div>
	<div className="flexrow">
		<div className="col-xs-4"><a onClick={this.export}><Icon name="download" fixedWidth /> Export Entry</a></div>
		<div className="col-xs-4"><a onClick={this.delete}><Icon name="chain-broken" fixedWidth /> Delete Entry</a></div>
		<div className="col-xs-4"><a onClick={this.rename}><Icon name="i-cursor" fixedWidth /> Rename Entry</a></div>
	</div>
	<br />
	<DataInput handleFile={this.handle} title={`Replace file contents`} />
	<div className="minor">You can also drag and drop a file.</div><br/>
	<details>
		<summary><b>Entry Metadata</b> (click to show)</summary>
		<b>Full Path:</b> {_FP}<br />
		<b>Size:</b> {_size} bytes<br />
		<b>CRC32:</b> {_crc32}<br />
	</details>
	<br />
	<b>
		{partial ? `Showing First ${THRESH} Bytes` : "Showing File Contents"}
		{partial && ( <Link to={`/view/${this.props.idx}/full`}> (Full Contents) </Link> )}
		{show_link && show_link != this.props.mode && ( <Link to={`/view/${this.props.idx}/${show_link}`} onClick={this.stload}> (View as {show_link_txt}) </Link> )}
	</b>
	{this.state.loading ? (
		<Spinner name="line-scale-pulse-out" fadeIn="none" />
	) : show_text ? (
		<SyntaxHighlighter style={arduinoLight} customStyle={{width:`calc(100vw - ${this.props.viz ? 300 : 50}px)`}}>{doxml ? xml(T) : T}</SyntaxHighlighter>
	) : show_imag ? (
		<div>
			<img src={I} />
		</div>
	) : !indices.length ? (
		<pre>(file is empty)</pre>
	) : (
		<pre>{indexData}</pre>
	)}
</div>
		);
		return out;
	}
}
export default easyComp(FileView);
