/*** @jsx React.DOM */

function count_pcbids(machines) {
    var count = 0;
    machines.map(function(machine) {
        count += (machine.editable ? 1 : 0);
    });
    return count;
}

var arcade_management = React.createClass({
    getInitialState: function(props) {
        var credits = {};
        Object.keys(window.users).map(function(userid) {
            credits[userid] = '';
        });
        return {
            id: window.arcade.id,
            name: window.arcade.name,
            description: window.arcade.description,
            paseli_enabled: window.arcade.paseli_enabled,
            paseli_infinite: window.arcade.paseli_infinite,
            mask_services_url: window.arcade.mask_services_url,
            pin: window.arcade.pin,
            editing_pin: false,
            new_pin: '',
            region: window.arcade.region,
            editing_region: false,
            new_region: '',
            paseli_enabled_saving: false,
            paseli_infinite_saving: false,
            mask_services_url_saving: false,
            editing_machine: null,
            machines: window.machines,
            pcbcount: count_pcbids(window.machines),
            random_pcbid: {
                description: '',
            },
            users: window.users,
            balances: window.balances,
            credits: credits,
            events: window.events,
            eventoffset: 0,
            eventlimit: 5,
            credit_card: '',
            credit_amount: '',
        };
    },

    componentDidMount: function() {
        this.refreshArcade();
    },

    componentDidUpdate: function() {
        if (this.focus_element && this.focus_element != this.already_focused) {
            this.focus_element.focus();
            this.already_focused = this.focus_element;
        }
    },

    refreshArcade: function() {
        AJAX.get(
            Link.get('refresh'),
            function(response) {
                this.setState({
                    users: response.users,
                    balances: response.balances,
                    machines: response.machines,
                    pcbcount: count_pcbids(response.machines),
                    events: response.events,
                });
                // Refresh every 5 seconds
                setTimeout(this.refreshArcade, 5000);
            }.bind(this)
        );
    },

    savePin: function(event) {
        AJAX.post(
            Link.get('update_pin'),
            {pin: this.state.new_pin},
            function(response) {
                this.setState({
                    pin: response.pin,
                    new_pin: '',
                    editing_pin: false,
                });
            }.bind(this)
        );
        event.preventDefault();
    },

    saveRegion: function(event) {
        AJAX.post(
            Link.get('update_region'),
            {region: this.state.new_region},
            function(response) {
                this.setState({
                    region: response.region,
                    new_region: '',
                    editing_region: false,
                });
            }.bind(this)
        );
        event.preventDefault();
    },

    togglePaseliEnabled: function(event) {
        this.setState({paseli_enabled_saving: true})
        AJAX.post(
            Link.get('paseli_enabled'),
            {value: !this.state.paseli_enabled},
            function(response) {
                this.setState({
                    paseli_enabled: response.value,
                    paseli_enabled_saving: false,
                });
            }.bind(this)
        );
        event.preventDefault();
    },

    togglePaseliInfinite: function(event) {
        this.setState({paseli_infinite_saving: true})
        AJAX.post(
            Link.get('paseli_infinite'),
            {value: !this.state.paseli_infinite},
            function(response) {
                this.setState({
                    paseli_infinite: response.value,
                    paseli_infinite_saving: false,
                });
            }.bind(this)
        );
        event.preventDefault();
    },

    toggleMaskServicesURL: function(event) {
        this.setState({mask_services_url_saving: true})
        AJAX.post(
            Link.get('mask_services_url'),
            {value: !this.state.mask_services_url},
            function(response) {
                this.setState({
                    mask_services_url: response.value,
                    mask_services_url_saving: false,
                });
            }.bind(this)
        );
        event.preventDefault();
    },

    addBalance: function(event) {
        var intval = parseInt(this.state.credit_amount);
        if (isNaN(intval)) {
            intval = 0;
        }
        AJAX.post(
            Link.get('add_balance'),
            {
                credits: intval,
                card: this.state.credit_card,
            },
            function(response) {
                var credits = {};
                Object.keys(response.users).map(function(userid) {
                    credits[userid] = '';
                });
                console.log('huh?');
                this.setState({
                    users: response.users,
                    balances: response.balances,
                    credits: credits,
                    events: response.events,
                    credit_card: '',
                    credit_amount: '',
                });
            }.bind(this)
        );
        event.preventDefault();
    },

    updateBalance: function(event) {
        var updates = {};
        Object.keys(this.state.credits).map(function(userid) {
            var intval = parseInt(this.state.credits[userid]);
            if (!isNaN(intval)) {
                updates[userid] = intval;
            }
        }.bind(this));
        AJAX.post(
            Link.get('update_balance'),
            {credits: updates},
            function(response) {
                var credits = {};
                Object.keys(response.users).map(function(userid) {
                    credits[userid] = '';
                });
                this.setState({
                    users: response.users,
                    balances: response.balances,
                    credits: credits,
                    events: response.events,
                });
            }.bind(this)
        );
        event.preventDefault();
    },

    renderPIN: function() {
        return (
            <LabelledSection vertical={true} label="PIN">{
                !this.state.editing_pin ?
                    <span>
                        <span>{this.state.pin}</span>
                        <Edit
                            onClick={function(event) {
                                this.setState({editing_pin: true, new_pin: this.state.pin});
                            }.bind(this)}
                        />
                    </span> :
                    <form className="inline" onSubmit={this.savePin}>
                        <input
                            type="text"
                            className="inline"
                            maxlength="8"
                            size="8"
                            autofocus="true"
                            ref={c => (this.focus_element = c)}
                            value={this.state.new_pin}
                            onChange={function(event) {
                                var intRegex = /^\d*$/;
                                if (event.target.value.length <= 8 && intRegex.test(event.target.value)) {
                                    this.setState({new_pin: event.target.value});
                                }
                            }.bind(this)}
                            name="pin"
                        />
                        <input
                            type="submit"
                            value="save"
                        />
                        <input
                            type="button"
                            value="cancel"
                            onClick={function(event) {
                                this.setState({
                                    new_pin: '',
                                    editing_pin: false,
                                });
                            }.bind(this)}
                        />
                    </form>
            }</LabelledSection>
        );
    },

    renderRegion: function() {
        return (
            <LabelledSection vertical={true} label="Region">{
                !this.state.editing_region ?
                    <span>
                        <span>{ window.regions[this.state.region] }</span>
                        <Edit
                            onClick={function(event) {
                                this.setState({editing_region: true, new_region: this.state.region});
                            }.bind(this)}
                        />
                    </span> :
                    <form className="inline" onSubmit={this.saveRegion}>
                        <SelectInt
                            name="region"
                            value={ this.state.new_region }
                            choices={ window.regions }
                            onChange={function(choice) {
                                this.setState({new_region: event.target.value});
                            }.bind(this)}
                        />
                        <input
                            type="submit"
                            value="save"
                        />
                        <input
                            type="button"
                            value="cancel"
                            onClick={function(event) {
                                this.setState({
                                    new_region: '',
                                    editing_region: false,
                                });
                            }.bind(this)}
                        />
                    </form>
            }</LabelledSection>
        );
    },

    generateNewMachine: function(event) {
        AJAX.post(
            Link.get('generatepcbid'),
            {machine: this.state.random_pcbid},
            function(response) {
                this.setState({
                    machines: response.machines,
                    pcbcount: count_pcbids(response.machines),
                    random_pcbid: {
                        description: '',
                    },
                });
            }.bind(this)
        );
        event.preventDefault();
    },

    deleteExistingMachine: function(event, pcbid) {
        $.confirm({
            escapeKey: 'Cancel',
            animation: 'none',
            closeAnimation: 'none',
            title: 'Delete PCBID',
            content: 'Are you sure you want to delete this PCBID from the network?',
            buttons: {
                Delete: {
                    btnClass: 'delete',
                    action: function() {
                        AJAX.post(
                            Link.get('removepcbid'),
                            {pcbid: pcbid},
                            function(response) {
                                this.setState({
                                    machines: response.machines,
                                    pcbcount: count_pcbids(response.machines),
                                });
                            }.bind(this)
                        );
                    }.bind(this),
                },
                Cancel: function() {
                },
            }
        });
        event.preventDefault();
    },

    saveMachine: function(event) {
        machine = this.state.editing_machine;
        if (machine.port == '') {
            machine.port = 0;
        }

        AJAX.post(
            Link.get('updatepcbid'),
            {machine: this.state.editing_machine},
            function(response) {
                this.setState({
                    machines: response.machines,
                    pcbcount: count_pcbids(response.machines),
                    editing_machine: null,
                });
            }.bind(this)
        );
        event.preventDefault();
    },

    renderDescription: function(machine) {
        if (this.state.editing_machine && machine.pcbid == this.state.editing_machine.pcbid) {
            return <input
                name="description"
                type="text"
                autofocus="true"
                ref={c => (this.focus_element = c)}
                value={ this.state.editing_machine.description }
                onChange={function(event) {
                    var machine = this.state.editing_machine;
                    machine.description = event.target.value;
                    this.setState({
                        editing_machine: machine,
                    });
                }.bind(this)}
            />;
        } else {
            return (
                <span>{ machine.description }</span>
            );
        }
    },

    renderPort: function(machine) {
        if (this.state.editing_machine && machine.pcbid == this.state.editing_machine.pcbid) {
            return <input
                name="port"
                type="text"
                value={ this.state.editing_machine.port }
                onChange={function(event) {
                    var machine = this.state.editing_machine;
                    var intRegex = /^\d*$/;
                    if (intRegex.test(event.target.value)) {
                        if (event.target.value.length > 0) {
                            machine.port = parseInt(event.target.value);
                        } else {
                            machine.port = '';
                        }
                        this.setState({
                            editing_machine: machine,
                        });
                    }
                }.bind(this)}
            />;
        } else {
            return (
                <span>{ machine.port }</span>
            );
        }
    },

    renderEditButton: function(machine) {
        if (this.state.editing_machine) {
            if (this.state.editing_machine.pcbid == machine.pcbid) {
                return (
                    <span>
                        <input
                            type="submit"
                            value="save"
                        />
                        <input
                            type="button"
                            value="cancel"
                            onClick={function(event) {
                                this.setState({
                                    editing_machine: null,
                                });
                            }.bind(this)}
                        />
                    </span>
                );
            } else {
                return <span></span>;
            }
        } else {
            if (window.max_pcbids > 0 && machine.editable) {
                return (
                    <span>
                        <Edit
                            onClick={function(event) {
                                var editing_machine = null;
                                this.state.machines.map(function(a) {
                                    if (a.pcbid == machine.pcbid) {
                                        editing_machine = jQuery.extend(true, {}, a);
                                    }
                                });
                                this.setState({
                                    editing_machine: editing_machine,
                                });
                            }.bind(this)}
                        />
                        <Delete
                            onClick={function(event) {
                                this.deleteExistingMachine(event, machine.pcbid);
                            }.bind(this)}
                        />
                    </span>
                );
            } else {
                return <span></span>;
            }
        }
    },

    render: function() {
        return (
            <div>
                <div className="section">
                    <LabelledSection vertical={true} label="Name">{ this.state.name }</LabelledSection>
                    <LabelledSection vertical={true} label="Description">{
                        this.state.description ?
                            <span>{ this.state.description }</span> :
                            <span className="placeholder">no description</span>
                    }</LabelledSection>
                    {this.renderPIN()}
                    {this.renderRegion()}
                    <LabelledSection vertical={true} label="PASELI Enabled">
                        <span>{ this.state.paseli_enabled ? 'yes' : 'no' }</span>
                        <Toggle onClick={this.togglePaseliEnabled.bind(this)} />
                        { this.state.paseli_enabled_saving ?
                            <img className="loading" src={Link.get('static', 'loading-16.gif')} /> :
                            null
                        }
                    </LabelledSection>
                    <LabelledSection vertical={true} label="PASELI Infinite">
                        <span>{ this.state.paseli_infinite ? 'yes' : 'no' }</span>
                        <Toggle onClick={this.togglePaseliInfinite.bind(this)} />
                        { this.state.paseli_infinite_saving ?
                            <img className="loading" src={Link.get('static', 'loading-16.gif')} /> :
                            null
                        }
                    </LabelledSection>
                    <LabelledSection vertical={true} label="Mask Web Address">
                        <span>{ this.state.mask_services_url ? 'yes' : 'no' }</span>
                        <Toggle onClick={this.toggleMaskServicesURL.bind(this)} />
                        { this.state.mask_services_url_saving ?
                            <img className="loading" src={Link.get('static', 'loading-16.gif')} /> :
                            null
                        }
                    </LabelledSection>
                </div>
                <div className="section">
                    <h3>PCBIDs Assigned to This Arcade</h3>
                    <form className="inline" onSubmit={this.saveMachine}>
                        <Table
                            className="list machine"
                            columns={[
                                {
                                    name: "PCBID",
                                    render: function(machine) { return machine.pcbid; },
                                    sort: function(a, b) { return a.pcbid.localeCompare(b.pcbid); },
                                },
                                {
                                    name: "Name",
                                    render: function(machine) { return machine.name; },
                                    sort: function(a, b) { return a.name.localeCompare(b.name); },
                                },
                                {
                                    name: "Description",
                                    render: this.renderDescription,
                                    sort: function(a, b) { return a.description.localeCompare(b.description); },
                                },
                                {
                                    name: "Applicable Game",
                                    render: function(machine) { return machine.game; },
                                    sort: function(a, b) { return a.game.localeCompare(b.game); },
                                    hidden: !window.enforcing,
                                },
                                {
                                    name: "Port",
                                    render: this.renderPort,
                                    sort: function(a, b) { return a.port - b.port; },
                                },
                                {
                                    name: '',
                                    render: this.renderEditButton,
                                    hidden: !window.enforcing || window.max_pcbids < 1,
                                    action: true,
                                },
                            ]}
                            rows={this.state.machines}
                            emptymessage="There are no PCBIDs assigned to this arcade."
                        />
                    </form>
                </div>
                { window.enforcing && this.state.pcbcount < window.max_pcbids ?
                    <div className="section">
                        <h3>Generate PCBID</h3>
                        <form className="inline" onSubmit={this.generateNewMachine}>
                            <table className="add machine">
                                <thead>
                                    <tr>
                                        <th>Description</th>
                                        <th></th>
                                    </tr>
                                </thead>
                                <tbody>
                                    <tr>
                                        <td>
                                            <input
                                                name="description"
                                                type="text"
                                                value={ this.state.random_pcbid.description }
                                                onChange={function(event) {
                                                    var pcbid = this.state.random_pcbid;
                                                    pcbid.description = event.target.value;
                                                    this.setState({random_pcbid: pcbid});
                                                }.bind(this)}
                                            />
                                        </td>
                                        <td>
                                            <input
                                                type="submit"
                                                value="generate PCBID"
                                            />
                                        </td>
                                    </tr>
                                </tbody>
                            </table>
                        </form>
                    </div>
                    : null
                }
                <div className="section">
                    <h3>Game Settings For This Arcade</h3>
                    <GameSettings game_settings={window.game_settings} />
                </div>
                <div className="section">
                    <h3>User PASELI Balances for This Arcade</h3>
                    { Object.keys(this.state.balances).length == 0 ?
                        <div>
                            <span className="placeholder">No users with balances for this arcade!</span>
                        </div> :
                        <form onSubmit={this.updateBalance}>
                            <table className="list blance">
                                <thead>
                                    <tr>
                                        <th>User</th>
                                        <th>Current Balance</th>
                                        <th>Credit Amount</th>
                                    </tr>
                                </thead>
                                <tbody>
                                    {Object.keys(this.state.balances).map(function(userid) {
                                        var user = this.state.users[userid];
                                        return (
                                            <tr>
                                                <td>{ user ?
                                                    <span>{user}</span> :
                                                    <span className="placeholder">anonymous account</span>
                                                }</td>
                                                <td>{this.state.balances[userid]}</td>
                                                <td>
                                                    <input
                                                        type="text"
                                                        className="inline"
                                                        value={this.state.credits[userid]}
                                                        onChange={function(event) {
                                                            var credits = this.state.credits;
                                                            credits[userid] = event.target.value;
                                                            this.setState({credits: credits});
                                                        }.bind(this)}
                                                        name="credits"
                                                    />
                                                </td>
                                            </tr>
                                        );
                                    }.bind(this))}
                                </tbody>
                            </table>
                            <div className="action">
                                <input type="submit" value="update balance" />
                            </div>
                        </form>
                    }
                </div>
                <div className="section">
                    <h3>Credit PASELI via Card</h3>
                    <form onSubmit={this.addBalance}>
                        <table className="add blance">
                            <thead>
                                <tr>
                                    <th>Card Number</th>
                                    <th>Credit Amount</th>
                                    <th></th>
                                </tr>
                            </thead>
                            <tbody>
                                <tr>
                                    <td>
                                        <input
                                            type="text"
                                            className="inline"
                                            value={this.state.credit_card}
                                            onChange={function(event) {
                                                this.setState({credit_card: event.target.value});
                                            }.bind(this)}
                                            name="card"
                                        />
                                    </td>
                                    <td>
                                        <input
                                            type="text"
                                            className="inline"
                                            value={this.state.credit_amount}
                                            onChange={function(event) {
                                                this.setState({credit_amount: event.target.value});
                                            }.bind(this)}
                                            name="credits"
                                        />
                                    </td>
                                    <td>
                                        <input type="submit" value="update balance" />
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                    </form>
                </div>
                <div className="section">
                    <h3>PASELI Transaction History</h3>
                    { this.state.events.length == 0 ?
                        <div>
                            <span className="placeholder">No events to display!</span>
                        </div> :
                        <table className="list events">
                            <thead>
                                <tr>
                                    <th>Timestamp</th>
                                    <th>Event</th>
                                    <th>Details</th>
                                </tr>
                            </thead>
                            <tbody>
                                {this.state.events.map(function(event, index) {
                                    if (index < this.state.eventoffset || index >= this.state.eventoffset + this.state.eventlimit) {
                                        return null;
                                    }

                                    if(event.type == 'paseli_transaction') {
                                        return <PASELITransactionEvent event={event} users={this.state.users} />;
                                    } else {
                                        return null;
                                    }
                                }.bind(this))}
                            </tbody>
                            <tfoot>
                                <tr>
                                    <td colSpan={3}>
                                        { this.state.eventoffset > 0 ?
                                            <Prev onClick={function(event) {
                                                 var page = this.state.eventoffset - this.state.eventlimit;
                                                 if (page < 0) { page = 0; }
                                                 this.setState({eventoffset: page});
                                            }.bind(this)}/> : null
                                        }
                                        { (this.state.eventoffset + this.state.eventlimit) < this.state.events.length ?
                                            <Next style={ {float: 'right'} } onClick={function(event) {
                                                 var page = this.state.eventoffset + this.state.eventlimit;
                                                 if (page >= this.state.events.length) { return }
                                                 this.setState({eventoffset: page});
                                            }.bind(this)}/> : null
                                        }
                                    </td>
                                </tr>
                            </tfoot>
                        </table>
                    }
                </div>
            </div>
        );
    },
});

ReactDOM.render(
    React.createElement(arcade_management, null),
    document.getElementById('content')
);
