import React from "react";
import ReactDOM from 'react-dom';
import _ from "lodash";
import {FlowActions} from "../../actions.js";
import {RequestUtils, isValidHttpVersion, parseUrl, parseHttpVersion} from "../../flow/utils.js";
import {Key, formatTimeStamp} from "../../utils.js";
import ContentView from "./contentview.js";
import {ValueEditor} from "../editor.js";
var Headers = React.createClass({
    propTypes: {
        onChange: React.PropTypes.func.isRequired,
        message: React.PropTypes.object.isRequired
    },
    onChange: function (row, col, val) {
        var nextHeaders = _.cloneDeep(this.props.message.headers);
        nextHeaders[row][col] = val;
        if (!nextHeaders[row][0] && !nextHeaders[row][1]) {
            // do not delete last row
            if (nextHeaders.length === 1) {
                nextHeaders[0][0] = "Name";
                nextHeaders[0][1] = "Value";
            } else {
                nextHeaders.splice(row, 1);
                // manually move selection target if this has been the last row.
                if (row === nextHeaders.length) {
                    this._nextSel = (row - 1) + "-value";
                }
            }
        }
        this.props.onChange(nextHeaders);
    },
    edit: function () {
        this.refs["0-key"].focus();
    },
    onTab: function (row, col, e) {
        var headers = this.props.message.headers;
        if (row === headers.length - 1 && col === 1) {
            e.preventDefault();
            var nextHeaders = _.cloneDeep(this.props.message.headers);
            nextHeaders.push(["Name", "Value"]);
            this.props.onChange(nextHeaders);
            this._nextSel = (row + 1) + "-key";
        }
    },
    componentDidUpdate: function () {
        if (this._nextSel && this.refs[this._nextSel]) {
            this.refs[this._nextSel].focus();
            this._nextSel = undefined;
        }
    },
    onRemove: function (row, col, e) {
        if (col === 1) {
            e.preventDefault();
            this.refs[row + "-key"].focus();
        } else if (row > 0) {
            e.preventDefault();
            this.refs[(row - 1) + "-value"].focus();
        }
    },
    render: function () {
        var rows = this.props.message.headers.map(function (header, i) {
            var kEdit = ;
            var vEdit = ;
            return (
                
                    | {kEdit}: | {vEdit} | 
            );
        }.bind(this));
        return (
            
        );
    }
});
var HeaderEditor = React.createClass({
    render: function () {
        return ;
    },
    focus: function () {
        ReactDOM.findDOMNode(this).focus();
    },
    onKeyDown: function (e) {
        switch (e.keyCode) {
            case Key.BACKSPACE:
                var s = window.getSelection().getRangeAt(0);
                if (s.startOffset === 0 && s.endOffset === 0) {
                    this.props.onRemove(e);
                }
                break;
            case Key.TAB:
                if (!e.shiftKey) {
                    this.props.onTab(e);
                }
                break;
        }
    }
});
var RequestLine = React.createClass({
    render: function () {
        var flow = this.props.flow;
        var url = RequestUtils.pretty_url(flow.request);
        var httpver = flow.request.http_version;
        return 
            
         
            
         
            
        
    },
    isValidUrl: function (url) {
        var u = parseUrl(url);
        return !!u.host;
    },
    onMethodChange: function (nextMethod) {
        FlowActions.update(
            this.props.flow,
            {request: {method: nextMethod}}
        );
    },
    onUrlChange: function (nextUrl) {
        var props = parseUrl(nextUrl);
        props.path = props.path || "";
        FlowActions.update(
            this.props.flow,
            {request: props}
        );
    },
    onHttpVersionChange: function (nextVer) {
        var ver = parseHttpVersion(nextVer);
        FlowActions.update(
            this.props.flow,
            {request: {http_version: ver}}
        );
    }
});
var ResponseLine = React.createClass({
    render: function () {
        var flow = this.props.flow;
        var httpver = flow.response.http_version;
        return 
            
         
            
         
            
        
;
    },
    isValidCode: function (code) {
        return /^\d+$/.test(code);
    },
    onHttpVersionChange: function (nextVer) {
        var ver = parseHttpVersion(nextVer);
        FlowActions.update(
            this.props.flow,
            {response: {http_version: ver}}
        );
    },
    onMsgChange: function (nextMsg) {
        FlowActions.update(
            this.props.flow,
            {response: {msg: nextMsg}}
        );
    },
    onCodeChange: function (nextCode) {
        nextCode = parseInt(nextCode);
        FlowActions.update(
            this.props.flow,
            {response: {code: nextCode}}
        );
    }
});
export var Request = React.createClass({
    render: function () {
        var flow = this.props.flow;
        return (
            
        );
    },
    edit: function (k) {
        switch (k) {
            case "m":
                this.refs.requestLine.refs.method.focus();
                break;
            case "u":
                this.refs.requestLine.refs.url.focus();
                break;
            case "v":
                this.refs.requestLine.refs.httpVersion.focus();
                break;
            case "h":
                this.refs.headers.edit();
                break;
            default:
                throw "Unimplemented: " + k;
        }
    },
    onHeaderChange: function (nextHeaders) {
        FlowActions.update(this.props.flow, {
            request: {
                headers: nextHeaders
            }
        });
    }
});
export var Response = React.createClass({
    render: function () {
        var flow = this.props.flow;
        return (
            
        );
    },
    edit: function (k) {
        switch (k) {
            case "c":
                this.refs.responseLine.refs.status_code.focus();
                break;
            case "m":
                this.refs.responseLine.refs.msg.focus();
                break;
            case "v":
                this.refs.responseLine.refs.httpVersion.focus();
                break;
            case "h":
                this.refs.headers.edit();
                break;
            default:
                throw "Unimplemented: " + k;
        }
    },
    onHeaderChange: function (nextHeaders) {
        FlowActions.update(this.props.flow, {
            response: {
                headers: nextHeaders
            }
        });
    }
});
export var Error = React.createClass({
    render: function () {
        var flow = this.props.flow;
        return (
            
                
                {flow.error.msg}
                    
                        { formatTimeStamp(flow.error.timestamp) }