import React, { Component } from 'react'
import PropTypes from 'prop-types'
import _ from "lodash"
import classnames from 'classnames'

import { Key } from '../../utils'

export default class ValueEditor extends Component {

    static propTypes = {
        content: PropTypes.string.isRequired,
        readonly: PropTypes.bool,
        onDone: PropTypes.func.isRequired,
        className: PropTypes.string,
        onInput: PropTypes.func,
        onKeyDown: PropTypes.func,
    }

    static defaultProps = {
        onInput: () => {},
        onKeyDown: () => {},
    }

    constructor(props) {
        super(props)
        this.state = { editable: false }

        this.onPaste = this.onPaste.bind(this)
        this.onMouseDown = this.onMouseDown.bind(this)
        this.onMouseUp = this.onMouseUp.bind(this)
        this.onFocus = this.onFocus.bind(this)
        this.onClick = this.onClick.bind(this)
        this.blur = this.blur.bind(this)
        this.onBlur = this.onBlur.bind(this)
        this.reset = this.reset.bind(this)
        this.onKeyDown = this.onKeyDown.bind(this)
        this.onInput = this.onInput.bind(this)
    }

    blur() {
        // a stop would cause a blur as a side-effect.
        // but a blur event must trigger a stop as well.
        // to fix this, make stop = blur and do the actual stop in the onBlur handler.
        this.input.blur()
    }

    reset() {
        this.input.innerHTML = _.escape(this.props.content)
    }

    render() {
        let className = classnames(
            'inline-input',
            {
                'readonly': this.props.readonly,
                'editable': !this.props.readonly
            },
            this.props.className
        )
        return (
            <div
                ref={input => this.input = input}
                tabIndex={this.props.readonly ? undefined : 0}
                className={className}
                contentEditable={this.state.editable || undefined}
                onFocus={this.onFocus}
                onMouseDown={this.onMouseDown}
                onClick={this.onClick}
                onBlur={this.onBlur}
                onKeyDown={this.onKeyDown}
                onInput={this.onInput}
                onPaste={this.onPaste}
                dangerouslySetInnerHTML={{ __html: _.escape(this.props.content) }}
            ></div>
        )
    }

    onPaste(e) {
        e.preventDefault()
        var content = e.clipboardData.getData('text/plain')
        document.execCommand('insertHTML', false, content)
    }

    onMouseDown(e) {
        this._mouseDown = true
        window.addEventListener('mouseup', this.onMouseUp)
    }

    onMouseUp() {
        if (this._mouseDown) {
            this._mouseDown = false
            window.removeEventListener('mouseup', this.onMouseUp)
        }
    }

    onClick(e) {
        this.onMouseUp()
        this.onFocus(e)
    }

    onFocus(e) {
        if (this._mouseDown || this._ignore_events || this.state.editable || this.props.readonly) {
            return
        }

        // contenteditable in FireFox is more or less broken.
        // - we need to blur() and then focus(), otherwise the caret is not shown.
        // - blur() + focus() == we need to save the caret position before
        //   Firefox sometimes just doesn't set a caret position => use caretPositionFromPoint
        const sel = window.getSelection()
        let range
        if (sel.rangeCount > 0) {
            range = sel.getRangeAt(0)
        } else if (document.caretPositionFromPoint && e.clientX && e.clientY) {
            const pos = document.caretPositionFromPoint(e.clientX, e.clientY)
            range = document.createRange()
            range.setStart(pos.offsetNode, pos.offset)
        } else if (document.caretRangeFromPoint && e.clientX && e.clientY) {
            range = document.caretRangeFromPoint(e.clientX, e.clientY)
        } else {
            range = document.createRange()
            range.selectNodeContents(this.input)
        }

        this._ignore_events = true
        this.setState({ editable: true }, () => {
            this.input.blur()
            this.input.focus()
            this._ignore_events = false
            range.selectNodeContents(this.input)
            sel.removeAllRanges();
            sel.addRange(range);
        })
    }

    onBlur(e) {
        if (this._ignore_events || this.props.readonly) {
            return
        }
        window.getSelection().removeAllRanges() //make sure that selection is cleared on blur
        this.setState({ editable: false })
        this.props.onDone(this.input.textContent)
    }


    onKeyDown(e) {
        e.stopPropagation()
        switch (e.keyCode) {
            case Key.ESC:
                e.preventDefault()
                this.reset()
                this.blur()
                break
            case Key.ENTER:
                if (!e.shiftKey) {
                    e.preventDefault()
                    this.blur()
                }
                break
            default:
                break
        }
        this.props.onKeyDown(e)
    }

    onInput() {
        this.props.onInput(this.input.textContent)
    }
}
' href='#n45'>45</a>
<a id='n46' href='#n46'>46</a>
<a id='n47' href='#n47'>47</a>
<a id='n48' href='#n48'>48</a>
<a id='n49' href='#n49'>49</a>
<a id='n50' href='#n50'>50</a>
<a id='n51' href='#n51'>51</a>
<a id='n52' href='#n52'>52</a>
<a id='n53' href='#n53'>53</a>
<a id='n54' href='#n54'>54</a>
<a id='n55' href='#n55'>55</a>
<a id='n56' href='#n56'>56</a>
<a id='n57' href='#n57'>57</a>
<a id='n58' href='#n58'>58</a>
<a id='n59' href='#n59'>59</a>
<a id='n60' href='#n60'>60</a>
<a id='n61' href='#n61'>61</a>
<a id='n62' href='#n62'>62</a>
<a id='n63' href='#n63'>63</a>
<a id='n64' href='#n64'>64</a>
<a id='n65' href='#n65'>65</a>
<a id='n66' href='#n66'>66</a>
<a id='n67' href='#n67'>67</a>
<a id='n68' href='#n68'>68</a>
<a id='n69' href='#n69'>69</a>
<a id='n70' href='#n70'>70</a>
<a id='n71' href='#n71'>71</a>
<a id='n72' href='#n72'>72</a>
<a id='n73' href='#n73'>73</a>
<a id='n74' href='#n74'>74</a>
<a id='n75' href='#n75'>75</a>
<a id='n76' href='#n76'>76</a>
<a id='n77' href='#n77'>77</a>
<a id='n78' href='#n78'>78</a>
<a id='n79' href='#n79'>79</a>
<a id='n80' href='#n80'>80</a>
<a id='n81' href='#n81'>81</a>
<a id='n82' href='#n82'>82</a>
<a id='n83' href='#n83'>83</a>
<a id='n84' href='#n84'>84</a>
<a id='n85' href='#n85'>85</a>
<a id='n86' href='#n86'>86</a>
<a id='n87' href='#n87'>87</a>
<a id='n88' href='#n88'>88</a>
<a id='n89' href='#n89'>89</a>
<a id='n90' href='#n90'>90</a>
<a id='n91' href='#n91'>91</a>
<a id='n92' href='#n92'>92</a>
<a id='n93' href='#n93'>93</a>
<a id='n94' href='#n94'>94</a>
<a id='n95' href='#n95'>95</a>
<a id='n96' href='#n96'>96</a>
<a id='n97' href='#n97'>97</a>
<a id='n98' href='#n98'>98</a>
<a id='n99' href='#n99'>99</a>
<a id='n100' href='#n100'>100</a>
<a id='n101' href='#n101'>101</a>
<a id='n102' href='#n102'>102</a>
<a id='n103' href='#n103'>103</a>
<a id='n104' href='#n104'>104</a>
<a id='n105' href='#n105'>105</a>
<a id='n106' href='#n106'>106</a>
<a id='n107' href='#n107'>107</a>
<a id='n108' href='#n108'>108</a>
<a id='n109' href='#n109'>109</a>
<a id='n110' href='#n110'>110</a>
<a id='n111' href='#n111'>111</a>
<a id='n112' href='#n112'>112</a>
<a id='n113' href='#n113'>113</a>
<a id='n114' href='#n114'>114</a>
<a id='n115' href='#n115'>115</a>
<a id='n116' href='#n116'>116</a>
<a id='n117' href='#n117'>117</a>
<a id='n118' href='#n118'>118</a>
<a id='n119' href='#n119'>119</a>
<a id='n120' href='#n120'>120</a>
<a id='n121' href='#n121'>121</a>
<a id='n122' href='#n122'>122</a>
<a id='n123' href='#n123'>123</a>
<a id='n124' href='#n124'>124</a>
<a id='n125' href='#n125'>125</a>
<a id='n126' href='#n126'>126</a>
<a id='n127' href='#n127'>127</a>
<a id='n128' href='#n128'>128</a>
<a id='n129' href='#n129'>129</a>
<a id='n130' href='#n130'>130</a>
<a id='n131' href='#n131'>131</a>
<a id='n132' href='#n132'>132</a>
<a id='n133' href='#n133'>133</a>
<a id='n134' href='#n134'>134</a>
<a id='n135' href='#n135'>135</a>
<a id='n136' href='#n136'>136</a>
<a id='n137' href='#n137'>137</a>
<a id='n138' href='#n138'>138</a>
<a id='n139' href='#n139'>139</a>
<a id='n140' href='#n140'>140</a>
<a id='n141' href='#n141'>141</a>
<a id='n142' href='#n142'>142</a>
<a id='n143' href='#n143'>143</a>
<a id='n144' href='#n144'>144</a>
<a id='n145' href='#n145'>145</a>
<a id='n146' href='#n146'>146</a>
<a id='n147' href='#n147'>147</a>
<a id='n148' href='#n148'>148</a>
<a id='n149' href='#n149'>149</a>
<a id='n150' href='#n150'>150</a>
<a id='n151' href='#n151'>151</a>
<a id='n152' href='#n152'>152</a>
<a id='n153' href='#n153'>153</a>
<a id='n154' href='#n154'>154</a>
<a id='n155' href='#n155'>155</a>
<a id='n156' href='#n156'>156</a>
<a id='n157' href='#n157'>157</a>
<a id='n158' href='#n158'>158</a>
<a id='n159' href='#n159'>159</a>
<a id='n160' href='#n160'>160</a>
<a id='n161' href='#n161'>161</a>
<a id='n162' href='#n162'>162</a>
<a id='n163' href='#n163'>163</a>
<a id='n164' href='#n164'>164</a>
<a id='n165' href='#n165'>165</a>
<a id='n166' href='#n166'>166</a>
<a id='n167' href='#n167'>167</a>
<a id='n168' href='#n168'>168</a>
<a id='n169' href='#n169'>169</a>
</pre></td>
<td class='lines'><pre><code>