import React from 'react';
import superagent from 'superagent';
import ReactPlayer from 'react-player'

import DraggableTableRow from '../Util/DraggableTableRow.jsx';

import constants from '../CloudApi/Constants.js';

import {
    Container,
    Segment,
    Grid,
    Header,
    Image,
    Icon,
    Button,
    Table,
    Form,
    Label,
    Message,
    Menu,
    Tab,
    Dropdown,
    Modal,
    Card, 
    Divider} from 'semantic-ui-react'
import MoviesTVWrapper from './MoviesTVWrapper.jsx';

const Views = {
    Loading: "Loading",
    Channels: "Channels",
    ChannelEditor: "ChannelEditor",
    ChannelGroups: "ChannelGroups",
    ChannelGroupEditor: "ChannelGroupEditor"
}

class TVDashboard extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            query: null,

            currentChannel: null,
            currentChannelGroup: null,

            channels: [],
            channelGroups: [],

            selectedChannelId: null,

            plutoChannelQueries: null,

            currentVideoUri: null,

            view: Views.Loading,
            nextContent: constants.ContentQueryTypes[0].value,

            imageLoading: false,
            
            loading: false
        };
    }

    async componentDidMount() {
        if (this.props.match.params.channelId) {
            this.setState({ view: Views.Loading });
            try {
                const mediaProductTrailersRes = await superagent.get(`/api/admin/media/products?entitlementClass=FREE_FOR_ALL`).accept('json');
                const freeMediaProductOptions = mediaProductTrailersRes.body.map(mediaProduct => { 
                    return { 
                        "key": mediaProduct.bigMediaId,
                        "value": mediaProduct.bigMediaId,
                        "text": `${mediaProduct.title}`,
                        "image": { src: mediaProduct.marketingData["en-US"].unityPosterTexture && mediaProduct.marketingData["en-US"].unityPosterTexture["src"] }
                    }
                });
                this.setState({ mediaProductTrailers: mediaProductTrailersRes.body, freeMediaProductOptions });

                const response = await superagent.get("/api/admin/tv/channel/" + this.props.match.params.channelId);
                this.setState({ currentChannel: response.body, view: Views.ChannelEditor, loading: false });
            } catch (e) {
                console.log(e);
            }
        } else if (this.props.match.params.channelGroupId) {
            this.setState({ view: Views.Loading });
            try {
                const channelsResponse = await superagent.get("/api/admin/tv/channels");
                const response = await superagent.get("/api/admin/tv/channel_group/" + this.props.match.params.channelGroupId);
                this.setState({ channels: channelsResponse.body, currentChannelGroup: response.body, view: Views.ChannelGroupEditor, loading: false });
            } catch (e) {
                console.log(e);
            }
        } else if (this.props.view) {
            if (this.props.view === Views.ChannelGroups) {
                await this.onShowChannelGroups();
            } else if (this.props.views === Views.Channels) {
                await this.onShowChannels();
            } else {
                await this.onShowChannels();
            }
        } else {
            await this.onShowChannels();
        }

        await this.getChannelQueryOptions();
    }

    refreshData() {

    }
    
    onChange(e, { name, value }) {
        this.setState({ [name]: value })
    }
    
    onChangeCurrentChannel(e, { name, value }) {
        if (this.state.currentChannel) {
            const _currentChannel = this.state.currentChannel;
            _currentChannel[name] = value;
            this.setState({ currentChannel: _currentChannel });
        } 
    }

    onChangeCurrentChannelRoomSettings(e, { name, value }) {
        if (this.state.currentChannel) {
            const _currentChannel = this.state.currentChannel;
            if (!_currentChannel.roomSettings) {
                _currentChannel.roomSettings = {};
            }
            _currentChannel.roomSettings[name] = value;
                
            console.log(_currentChannel);
            this.setState({ currentChannel: _currentChannel });
        } 
    }

    onChangeCurrentChannelGroup(e, { name, value }) {
        if (this.state.currentChannelGroup) {
            const _currentChannelGroup = this.state.currentChannelGroup;
            _currentChannelGroup[name] = value;
            this.setState({ currentChannelGroup: _currentChannelGroup });
        } 
    }

    async onShowChannels(e) {
        this.setState({ loading: true });
        const response = await superagent.get("/api/admin/tv/channels");
        this.setState({ channels: response.body, view: Views.Channels, loading: false });
    }

    onCreateChannel(e) {
        this.setState({ currentChannel: { geo: [], streams: [], queries: [], roomSettings: {} }, view: Views.ChannelEditor });
    }

    async onShowChannelGroups(e) {
        this.setState({ loading: true });
        const response = await superagent.get("/api/admin/tv/channel_groups");
        this.setState({ channelGroups: response.body, view: Views.ChannelGroups, loading: false });
    }

    async getChannelQueryOptions(e) {
        this.setState({ plutoChannelQueries: null });
        const response = await superagent.get("/api/admin/tv/channel_query/pluto");
        const options = response.body.map(nv => { return {"key": nv.value, "value": nv.value, "text": nv.name}});
        this.setState({ plutoChannelQueries: options });
    }

    onCreateChannelGroup(e) {
        this.setState({ currentChannelGroup: { channels: [] }, view: Views.ChannelGroupEditor });
    }

    async onSaveChannel(e) {
        try {
            this.setState({ loading: true });
            if (this.state.currentChannel) {
                if (this.state.currentChannel.id) {
                    const result = await superagent.put("/api/admin/tv/channel").send(this.state.currentChannel);
                    this.setState({ currentChannel: result.body, loading: false });
                } else {
                    const result = await superagent.post("/api/admin/tv/channel").send(this.state.currentChannel);
                    this.setState({ currentChannel: result.body, loading: false });
                }
            }
        } catch (e) {
            console.log(e);
        }
    }

    onAddStream(e) {
        e.preventDefault();
        let currentChannel = this.state.currentChannel;
        currentChannel.streams.push({
            type: this.state.nextContent,
            uri: ""
        });
        this.setState({currentChannel});
    }

    onAddQuery(e) {
        e.preventDefault();
        let currentChannel = this.state.currentChannel;
        currentChannel.queries.push({
            name: "twitch",
            value: ""
        });
        this.setState({currentChannel});
    }
    
    renderChannelEditor() {
        const geo = (this.state.currentChannel.geo.length == 0) ? <Label basic color="green">All Geographies</Label> :
        (
            <div>
            {this.state.currentChannel.geo.map(geo => {
                return (
                    <Label basic color="blue">{geo}</Label>
                )
            })}
            </div>
        );

        const details = (
            <div>
                <Form.Group>
                    <Form.Input required label='Name' value={this.state.currentChannel.name} name="name" onChange={this.onChangeCurrentChannel.bind(this)} />
                </Form.Group>
                <Form.Group widths="equal">
                    <Form.Input required label='Display Title' value={this.state.currentChannel.title} name="title" onChange={this.onChangeCurrentChannel.bind(this)} />
                </Form.Group>
                <Form.Group widths="equal">
                    <Form.Input required fluid label='Description' value={this.state.currentChannel.description} name="description" onChange={this.onChangeCurrentChannel.bind(this)} />
                </Form.Group>
            </div>
        );

        const extraDetail = (
            <div>
                <Form.Group  widths="equal">
                    <Form.Input label='Image URL (Preferably at least 500x500)' value={this.state.currentChannel.imageUrl} name="imageUrl" onChange={this.onChangeCurrentChannel.bind(this)} />
                </Form.Group>

                <Form.Group>
                    <Form.Field label="Allowed Geographies" /><br />
                    <p>{geo}</p>
                </Form.Group>
            </div>
        );

        const roomSettings = (
            <div>
                <Header as="h2">Room Settings</Header>

                <Form.Group widths="equal">
                    <Form.Select required label="Environment" size="small" name="environment" 
                    value={this.state.currentChannel.roomSettings.environment} 
                    options={constants.RoomEnvironments} 
                    onChange={this.onChangeCurrentChannelRoomSettings.bind(this)} />

                    <Form.Select required label="Size" size="small" name="size"
                    value={this.state.currentChannel.roomSettings.size} 
                    options={constants.RoomSizes} 
                    onChange={this.onChangeCurrentChannelRoomSettings.bind(this)} />
                </Form.Group>
            </div>
        );

        const channelContent = (
            <div>
                <Header as="h2">Channel Content</Header>
                <Header as="h4">Queries</Header>

                <Table celled striped>
                    {(this.state.currentChannel.queries.length > 0) && (
                        <Table.Header>
                            <Table.Row>
                                <Table.HeaderCell>Priority</Table.HeaderCell>
                                <Table.HeaderCell>Source</Table.HeaderCell>
                                <Table.HeaderCell>Value</Table.HeaderCell>
                                <Table.HeaderCell>Edit</Table.HeaderCell>
                            </Table.Row>
                        </Table.Header>
                    )}
                    <Table.Body>
                    {this.state.currentChannel.queries.map((query, queryIndex) => {
                        let onQueryChange = function(e, { name, value }) {
                            let currentChannel = this.state.currentChannel;
                            currentChannel.queries[queryIndex][name] = value;
                            this.setState({currentChannel});
                        }
                        let onRemoveQuery = function(e) {
                            let currentChannel = this.state.currentChannel;
                            currentChannel.queries.splice(queryIndex, 1);
                            this.setState({currentChannel});
                        }

                        let queryElement = <div />;
                        if (query.name === "pluto") {
                            queryElement = (
                            <Dropdown search selection 
                                placeholder="Type a channel name or choose an option..." 
                                icon='search'
                                fluid
                                loading={this.state.plutoChannelQueries === null}
                                size="small"
                                value={query.value}
                                name="value"
                                options={this.state.plutoChannelQueries}
                                onChange={onQueryChange.bind(this)} />
                            );
                        } else if (query.name === "twitch") {
                            queryElement = (
                                <Form.Input placeholder="Type the streamer name" value={query.value} name="value" onChange={onQueryChange.bind(this)} />
                            );
                        } else if (query.name === "youtube") {
                            queryElement = (
                                <div>
                                    <Form.Input placeholder="Enter the full URL to the Youtube livestream" value={query.value} name="value" onChange={onQueryChange.bind(this)} />
                                    <ReactPlayer url={query.value} playing controls muted />
                                </div>
                            );
                        } else if (query.name === "BigMediaProduct") {
                            queryElement = (
                                <Form.Dropdown search selection
                                    placeholder="Type a media product name or choose an option..."
                                    icon='search'
                                    loading={false}
                                    size="small"
                                    value={query.value}
                                    name="value"
                                    closeOnChange
                                    options={this.state.freeMediaProductOptions}
                                    onChange={onQueryChange.bind(this)} />
                            );
                        }

                        return (
                            <Table.Row>
                                <Table.Cell verticalAlign="top" collapsing width={1}>Query #{queryIndex + 1}</Table.Cell>
                                <Table.Cell width={4} verticalAlign="top">
                                    <Form.Select required size="small" name="name" value={query.name} options={constants.ContentQueryTypes} onChange={onQueryChange.bind(this)} />
                                </Table.Cell>
                                <Table.Cell width={10} verticalAlign="top">
                                    {queryElement}
                                </Table.Cell>
                                <Table.Cell collapsing>
                                    <Button onClick={onRemoveQuery.bind(this)}><Icon name='delete' />Remove</Button>
                                </Table.Cell>
                            </Table.Row>
                        )
                    })}
                    </Table.Body>
                    <Table.Footer fullWidth>
                        <Table.Row>
                            <Table.Cell colSpan='5'><Button onClick={this.onAddQuery.bind(this)}>Add query</Button></Table.Cell>
                        </Table.Row>
                    </Table.Footer>
                </Table>

                <Header as="h4">Streams</Header>
                
                <Table celled striped>
                    {(this.state.currentChannel.streams.length > 0) && (
                        <Table.Header>
                            <Table.Row>
                                <Table.HeaderCell>Priority</Table.HeaderCell>
                                <Table.HeaderCell>Data</Table.HeaderCell>
                                <Table.HeaderCell>Preview</Table.HeaderCell>
                                <Table.HeaderCell>Edit</Table.HeaderCell>
                            </Table.Row>
                        </Table.Header>
                    )}
                    <Table.Body>
                    {this.state.currentChannel.streams.map((stream, streamIndex) => {
                        let onStreamEntryChange = function(e, { name, value }) {
                            let currentChannel = this.state.currentChannel;
                            currentChannel.streams[streamIndex][name] = value;
                            this.setState({currentChannel});
                        }

                        let onMutedChanged = function(e) {
                            let currentChannel = this.state.currentChannel;
                            currentChannel.streams[streamIndex].isMuted = !currentChannel.streams[streamIndex].isMuted;
                            this.setState({currentChannel});
                        }

                        let onIsStaticFile = function(e) {
                            let currentChannel = this.state.currentChannel;
                            currentChannel.streams[streamIndex].onIsStaticFile = !currentChannel.streams[streamIndex].onIsStaticFile;
                            this.setState({currentChannel});
                        }

                        let onStereoChanged = function(e, { name, value }) {
                            let currentChannel = this.state.currentChannel;
                            if (value === 0) {
                                currentChannel.streams[streamIndex].isStereo = false;
                                currentChannel.streams[streamIndex].stereoPacking = "None";
                            } else if (value === 1) {
                                currentChannel.streams[streamIndex].isStereo = true;
                                currentChannel.streams[streamIndex].stereoPacking = "LeftRight";
                            } else if (value === 2) {
                                currentChannel.streams[streamIndex].isStereo = true;
                                currentChannel.streams[streamIndex].stereoPacking = "OverUnder";
                            }
                            this.setState({currentChannel});
                        }

                        let onRemoveStream = function(e) {
                            let currentChannel = this.state.currentChannel;
                            currentChannel.streams.splice(streamIndex, 1);
                            this.setState({currentChannel});
                        }

                        return (
                            <Table.Row>
                                <Table.Cell collapsing verticalAlign="top"><Label>#{streamIndex + 1}</Label></Table.Cell>
                                <Table.Cell width={9} verticalAlign="top">
                                    <Form.Group inline widths="equal">
                                        <label>URI</label>
                                        <Form.Input fluid required value={stream.uri} name="uri" onChange={onStreamEntryChange.bind(this)} />
                                    </Form.Group>
                                    <Form.Group inline>
                                        <label>Stereo</label>
                                        <Form.Radio label='Default (2D)' value={0} checked={stream.isStereo === false} onChange={onStereoChanged.bind(this)} />
                                        <Form.Radio label='Stereo 3D (Left/Right)' value={1} checked={stream.isStereo === true && stream.stereoPacking === "LeftRight"} onChange={onStereoChanged.bind(this)} />
                                        <Form.Radio label='Stereo 3D (Over/Under)' value={2} checked={stream.isStereo === true && stream.stereoPacking === "OverUnder"} onChange={onStereoChanged.bind(this)} />
                                    </Form.Group>
                                    <Form.Group inline widths="equal">
                                        <label>Format</label>
                                        <Form.Select required size="small" name="type" value={stream.type} options={constants.ContentStreamTypes} onChange={onStreamEntryChange.bind(this)} />
                                    </Form.Group>

                                    <Form.Checkbox label="Muted Stream?" checked={stream.isMuted} name="isMuted" onChange={onMutedChanged.bind(this)} />

                                    <Form.Checkbox label="Static File? (check this if the stream url is not a live stream)" checked={stream.isStaticFile} name="isStaticFile" onChange={onIsStaticFile.bind(this)} />
                                    
                                </Table.Cell>
                                <Table.Cell width={6} verticalAlign="top">
                                    <ReactPlayer url={stream.uri} playing controls muted />
                                </Table.Cell>
                                <Table.Cell collapsing>
                                    <Button onClick={onRemoveStream.bind(this)}><Icon name='delete' />Remove</Button>
                                </Table.Cell>
                            </Table.Row>
                        )
                    })}
                    </Table.Body>
                    <Table.Footer fullWidth>
                        <Table.Row>
                            <Table.HeaderCell colSpan='5'>
                                <Button onClick={this.onAddStream.bind(this)}>Add stream</Button>
                            </Table.HeaderCell>
                        </Table.Row>
                    </Table.Footer>
                </Table>
            </div>
        )

        const panes = [
            { menuItem: 'Details', render: () => <Tab.Pane attached={false}>{details}<Divider />{extraDetail}</Tab.Pane> },
            { menuItem: 'Room Settings', render: () => <Tab.Pane attached={false}>{roomSettings}</Tab.Pane> },
            { menuItem: 'Content', render: () => <Tab.Pane attached={false}>{channelContent}</Tab.Pane> }
        ];

        const tabs = (
            <Tab menu={{ secondary: true, pointing: true }} panes={panes} />
        );

//<Form.Input required label='Allowed Geographies' value={this.state.currentChannel.geo} name="geo" onChange={this.onChangeCurrentChannel.bind(this)} />
        return (
            <div>
            
            <Form size='small' onSubmit={this.onSaveChannel.bind(this)}>
                {(!this.state.currentChannel.id) && details}

                {(this.state.currentChannel.id) && (
                    (this.state.currentChannel.streams.length == 0 && this.state.currentChannel.queries.length == 0) && 
                    (<Message negative>
                        <Message.Header>This channel does not have any content!</Message.Header>
                        <p>Nobody will see the channel until you add a query or a stream</p>
                    </Message>)
                )}

                {(this.state.currentChannel.id) && tabs}
                
                <Segment basic>
                    {(!this.state.currentChannel.id) && <Form.Group><Button primary content='Create channel' type='submit' /></Form.Group>}
                    {(this.state.currentChannel.id) && <Form.Group><Button primary content='Save channel' type='submit' /></Form.Group>}
                </Segment>
            </Form>
            </div>
        )
    }

    onSelectChannel(channel, e) {
        this.props.history.push({pathname: `/tv/channel/${channel.id}`});
    }

    onSorted(clickedColumn) {
        const { channels, channelDirection } = this.state;
        const newChannelDirection = channelDirection === 'ascending' ? 'descending' : 'ascending';
        const sortedChannels = _.sortBy(channels, [clickedColumn]);
        if (newChannelDirection === "descending") {
            sortedChannels.reverse();
        }
        this.setState({
            channels: sortedChannels,
            channelDirection: newChannelDirection
        });
    }

    renderChannels() {
        return (
            <div>
                <Button color="blue" onClick={this.onCreateChannel.bind(this)}>Create a New Channel</Button>
                <Table celled selectable sortable>
                    <Table.Header>
                        <Table.Row>
                            <Table.HeaderCell onClick={this.onSorted.bind(this, "name")}>Name</Table.HeaderCell>
                            <Table.HeaderCell onClick={this.onSorted.bind(this, "title")}>Display title + description</Table.HeaderCell>
                            <Table.HeaderCell onClick={this.onSorted.bind(this, "geo.length")}>Geography</Table.HeaderCell>
                            <Table.HeaderCell onClick={this.onSorted.bind(this, "roomSettings.environment")}>Room Settings</Table.HeaderCell>
                            <Table.HeaderCell onClick={this.onSorted.bind(this, "streams.length")}>Active Streams</Table.HeaderCell>
                            <Table.HeaderCell onClick={this.onSorted.bind(this, "queries[0].name")}>Content Queries</Table.HeaderCell>
                        </Table.Row>
                    </Table.Header>
                    <Table.Body>
                    {this.state.channels.map((channel, channelIndex) => {
                        const streamData = channel.streams.length > 0 ? `${channel.streams.length} streams (${channel.streams[0].type})` : "";
                        const queryData = channel.queries.length > 0 ? `(${channel.queries[0].name})` : "";
                        const geo = (channel.geo.length == 0) ? <Label basic>All Geographies</Label> :
                        (
                            <div>
                            {channel.geo.map(geo => {
                                return (
                                    <Label basic color="blue">{geo}</Label>
                                )
                            })}
                            </div>
                        )
                        return (
                        <Table.Row style={{cursor: 'pointer'}} onClick={this.onSelectChannel.bind(this, channel)}>
                            <Table.Cell>{channel.name}</Table.Cell>
                            <Table.Cell>
                                <Header as='h4'>
                                    <Image src={channel.imageUrl} rounded size='small' verticalAlign='middle' floated='left' />
                                    {channel.title}<br />
                                    {channel.description}
                                </Header>
                                {(channel.streams.length === 0 && channel.queries.length === 0) && <Label as="a" color="red"><Icon name='warning sign' />No streams!</Label>}
                            </Table.Cell>
                            <Table.Cell>{geo}</Table.Cell>
                            <Table.Cell>{(channel.roomSettings) && <div>{channel.roomSettings.environment} (Size: {channel.roomSettings.size})</div>}</Table.Cell>
                            <Table.Cell>{streamData}</Table.Cell>
                            <Table.Cell>{queryData}</Table.Cell>
                        </Table.Row>
                        )
                    })}
                    </Table.Body>
                </Table>
            </div>
        )
    }

    onSelectChannelGroup(channelGroup, e) {
        this.props.history.push({pathname: `/tv/channel_group/${channelGroup.id}`});
    }

    renderChannelGroups() {
        return (
            <div>
                <Button color="blue" onClick={this.onCreateChannelGroup.bind(this)}>Create a New Channel Group</Button>
                <Table selectable>
                    <Table.Header>
                        <Table.Row>
                            <Table.HeaderCell collapsing>Name</Table.HeaderCell>
                            <Table.HeaderCell collapsing>Published</Table.HeaderCell>
                            <Table.HeaderCell collapsing>Notes</Table.HeaderCell>
                            <Table.HeaderCell>Display title</Table.HeaderCell>
                            <Table.HeaderCell>Number of Channels</Table.HeaderCell>
                            
                        </Table.Row>
                    </Table.Header>
                    <Table.Body>
                    {this.state.channelGroups.map((channelGroup, channelGroupIndex) => {
                        return (
                        <Table.Row style={{cursor: 'pointer'}} onClick={this.onSelectChannelGroup.bind(this, channelGroup)}>
                            <Table.Cell collapsing>
                                {channelGroup.name}
                            </Table.Cell>
                            <Table.Cell collapsing>
                                {(channelGroup.isPublished === false) && (<Icon circular color="green" name="check" />)}
                            </Table.Cell>
                            <Table.Cell collapsing>
                                {(channelGroup.channels.length === 0) && <Label as="a" color="red"><Icon name='warning sign' />No channels!</Label>}
                            </Table.Cell>
                            <Table.Cell>{channelGroup.title}</Table.Cell>
                            <Table.Cell>{channelGroup.channels.length}</Table.Cell>
                        </Table.Row>
                        )
                    })}
                    </Table.Body>
                </Table>
            </div>
        )
    }

    async onSaveChannelGroup(e) {
        try {
            this.setState({ loading: true });
            await superagent.put("/api/admin/tv/channel_group").send(this.state.currentChannelGroup);
            this.setState({ loading: false });
        } catch (e) {
            console.log(e);
        }
    }

    /**
     * The unity texture asset takes a while to generate - keep trying to load it until it shows up.
     */
    async tryLoadImage() {
        try {
            this.setState({ imageLoading: true });
            const result = await superagent.get(this.state.currentChannelGroup.textures[0].url);
            this.setState({ imageLoading: false });
        } catch (e) {
            setTimeout(this.tryLoadImage.bind(this), 500);
        }
    }

    renderChannelGroupEditor() {
        const channelSelectionList = this.state.channels.map(chan => {
            return { "key": chan.id, "value": chan.id, "text": `${chan.title} (${chan.name})` }
        });

        let onChannelSelectionChanged = function(e, { name, value }) {
            this.setState({selectedChannelId: value});
        }

        let onAddChannelToList = async function (e) {
            e.preventDefault();
            if (this.state.selectedChannelId) {
                
                const channel = _.find(this.state.channels, ["id", this.state.selectedChannelId]);

                const currentChannelGroup = this.state.currentChannelGroup;
                currentChannelGroup.channelIds.push(this.state.selectedChannelId);
                currentChannelGroup.channels.push(channel);
                this.setState({ currentChannelGroup });

                superagent.put("/api/admin/tv/channel_group").send(this.state.currentChannelGroup);
            }
        }

        let onRebuildChannelGroup = async function onRebuildChannelGroup() {
            try {
                this.setState({ loading: true });
                const result = await superagent.get("/api/admin/tv/rebuild_channel_group/" + this.state.currentChannelGroup.id);
                this.setState({ currentChannelGroup: result.body, loading: false });
                await this.tryLoadImage();
            } catch (e) {
                console.log(e);
            }
        }

        let onRemoveChannelFromList = async function(channelIndex, e) {
            e.preventDefault();
            if (this.state.currentChannelGroup) {
                const currentChannelGroup = this.state.currentChannelGroup;
                currentChannelGroup.channelIds.splice(channelIndex, 1);
                currentChannelGroup.channels.splice(channelIndex, 1);
                this.setState({ currentChannelGroup });

                superagent.put("/api/admin/tv/channel_group").send(this.state.currentChannelGroup);
            }
        }

        let onMoveChannelUp = async function(channelIndex, e) {
            e.preventDefault();
            if (this.state.currentChannelGroup) {
                const currentChannelGroup = this.state.currentChannelGroup;
                if(channelIndex > currentChannelGroup.channels.length || channelIndex == 0){
                    alert("top");
                    return;
                }
                const movedChannelId = currentChannelGroup.channelIds[channelIndex];
                const movedChannel = currentChannelGroup.channels[channelIndex];

                currentChannelGroup.channelIds.splice(channelIndex, 1);
                currentChannelGroup.channels.splice(channelIndex, 1);

                currentChannelGroup.channelIds.splice(channelIndex-1, 0, movedChannelId);
                currentChannelGroup.channels.splice(channelIndex-1, 0, movedChannel);

                this.setState({ currentChannelGroup });

                superagent.put("/api/admin/tv/channel_group").send(this.state.currentChannelGroup);
            }
        }

        let onMoveChannelDown = async function(channelIndex, e) {
            e.preventDefault();
            if (this.state.currentChannelGroup) {
                const currentChannelGroup = this.state.currentChannelGroup;
                if(channelIndex > currentChannelGroup.channels.length || channelIndex+1 == currentChannelGroup.channels.length){
                    alert('already bottom');
                    return;
                }
                const movedChannelId = currentChannelGroup.channelIds[channelIndex];
                const movedChannel = currentChannelGroup.channels[channelIndex];

                currentChannelGroup.channelIds.splice(channelIndex, 1);
                currentChannelGroup.channels.splice(channelIndex, 1);

                currentChannelGroup.channelIds.splice(channelIndex+1, 0, movedChannelId);
                currentChannelGroup.channels.splice(channelIndex+1, 0, movedChannel);

                this.setState({ currentChannelGroup });

                superagent.put("/api/admin/tv/channel_group").send(this.state.currentChannelGroup);
            }
        }

        let onMoveChannelToTop = async function(channelIndex, e) {
            e.preventDefault();
            if (this.state.currentChannelGroup) {
                const currentChannelGroup = this.state.currentChannelGroup;
                if(channelIndex > currentChannelGroup.channels.length || channelIndex == 0){
                    return;
                }
                const movedChannelId = currentChannelGroup.channelIds[channelIndex];
                const movedChannel = currentChannelGroup.channels[channelIndex];

                currentChannelGroup.channelIds.splice(channelIndex, 1);
                currentChannelGroup.channels.splice(channelIndex, 1);

                currentChannelGroup.channelIds.splice(0, 0, movedChannelId);
                currentChannelGroup.channels.splice(0, 0, movedChannel);

                this.setState({ currentChannelGroup });

                superagent.put("/api/admin/tv/channel_group").send(this.state.currentChannelGroup);
            }
        }

        let onChannelSwap = async function(channelIndexA, channelIndexB) {
            //e.preventDefault();

            if (channelIndexA >= this.state.currentChannelGroup.channelIds.length || channelIndexA < 0) {
                return;
            }

            console.log("dest", channelIndexA, "src", channelIndexB);
            if (this.state.currentChannelGroup) {
                const currentChannelGroup = this.state.currentChannelGroup;

                const movedChannelId = currentChannelGroup.channelIds[channelIndexB];
                currentChannelGroup.channelIds.splice(channelIndexB, 1);
                currentChannelGroup.channelIds.splice(channelIndexA, 0, movedChannelId);

                const movedChannel = currentChannelGroup.channels[channelIndexB];
                currentChannelGroup.channels.splice(channelIndexB, 1);
                currentChannelGroup.channels.splice(channelIndexA, 0, movedChannel);

                //currentChannelGroup.channelIds[channelIndexA] = currentChannelGroup.channelIds.splice(channelIndexB, 1, currentChannelGroup.channelIds)[0];
                //currentChannelGroup.channels[channelIndexA] = currentChannelGroup.channels.splice(channelIndexB, 1, currentChannelGroup.channels)[0];
                this.setState({ currentChannelGroup });

                superagent.put("/api/admin/tv/channel_group").send(this.state.currentChannelGroup);
            }
        }

        // <Form.Select required placeholder="Choose a channel..." size="small" name="type" value={this.state.selectedChannelId} options={channelSelectionList} onChange={onChannelSelectionChanged.bind(this)} />

        return (
            <div>
                <Form size='small' onSubmit={this.onSaveChannelGroup.bind(this)}>
                    {(this.state.currentChannelGroup.id) && <Form.Group><Button primary content='Save Channel Group' type='submit' /></Form.Group>}
                    
                    <Form.Group>
                        <Form.Input label='Unique identifier' autoComplete="off" width="3" value={this.state.currentChannelGroup.name} name="name" onChange={!this.state.currentChannelGroup.id && this.onChangeCurrentChannelGroup.bind(this)} />
                        {this.state.currentChannelGroup.id &&
                            <Form.Button label="&nbsp;" size="tiny" primary onClick={() => { this.setState({copyText: "Copied!"}); setTimeout(() => { this.setState({copyText: undefined})}, 2000); navigator.clipboard.writeText(this.state.currentChannelGroup.name)}}>{this.state.copyText || "Copy 😮"}</Form.Button>
                        }
                    </Form.Group>
                    <Form.Input width="6" label='Title' autoComplete="off" value={this.state.currentChannelGroup.title} name="title" onChange={this.onChangeCurrentChannelGroup.bind(this)} />

                    <Divider />

                    {(this.state.currentChannelGroup.id) && (
                        <Grid>
                            <Grid.Row>
                                <Grid.Column>
                                    <Header as="h2">Channels</Header>

                                    {(this.state.currentChannelGroup.channels.length == 0 && this.state.currentChannelGroup.channels.length == 0) &&
                                    (<Message negative>
                                        <Message.Header>This list does not have any channels!</Message.Header>
                                    </Message>)}

                                    <Table sortable selectable>
                                        <Table.Header fullWidth>
                                            <Table.Row>
                                                <Table.Cell colSpan='5'>
                                                    <Dropdown required search selection placeholder="Type a channel name or choose an option..." icon='search' fluid size="small" value={this.state.selectedChannelId} name="type" options={channelSelectionList} onChange={onChannelSelectionChanged.bind(this)} />
                                                    <Button onClick={onAddChannelToList.bind(this)}>Add channel to list</Button>
                                                </Table.Cell>
                                            </Table.Row>
                                            <Table.Row>
                                                <Table.HeaderCell>Channel</Table.HeaderCell>
                                                <Table.HeaderCell>Remove</Table.HeaderCell>
                                                <Table.HeaderCell>Move Up</Table.HeaderCell>
                                                <Table.HeaderCell>Move Down</Table.HeaderCell>
                                                <Table.HeaderCell>Move To Top</Table.HeaderCell>
                                            </Table.Row>
                                        </Table.Header>
                                        <Table.Body>
                                        {this.state.currentChannelGroup.channels.map((channel, channelIndex) => {
                                            return (
                                                <DraggableTableRow key={channelIndex} i={channelIndex} action={onChannelSwap.bind(this)}>
                                                    <Table.Cell width={15} style={{cursor: 'pointer'}} onClick={this.onSelectChannel.bind(this, channel)}>
                                                        <Header as='h4' image>
                                                            <Image src={channel.imageUrl} rounded verticalAlign='middle' floated='left' />

                                                            {channel.title}
                                                                <Header.Subheader>{channel.description}</Header.Subheader>
                                                        </Header>
                                                    </Table.Cell>
                                                    <Table.Cell collapsing>
                                                        <Button icon color="red" onClick={onRemoveChannelFromList.bind(this, channelIndex)}><Icon name='delete' /></Button>
                                                    </Table.Cell>
                                                    <Table.Cell collapsing>
                                                        <Button icon color="grey" onClick={onMoveChannelUp.bind(this, channelIndex)}><Icon name='angle up' /></Button>
                                                    </Table.Cell>
                                                    <Table.Cell collapsing>
                                                        <Button icon color="grey" onClick={onMoveChannelDown.bind(this, channelIndex)}><Icon name='angle down' /></Button>
                                                    </Table.Cell>
                                                    <Table.Cell collapsing>
                                                        <Button icon color="blue" onClick={onMoveChannelToTop.bind(this, channelIndex)}><Icon name='angle double up' /></Button>
                                                    </Table.Cell>
                                                </DraggableTableRow>
                                            );
                                        })}
                                        </Table.Body>
                                    </Table>
                                </Grid.Column>
                            </Grid.Row>
                            <Grid.Row>
                                <Grid.Column>
                                    <Header as="h2">Unity Texture</Header>
                                    <Message>
                                        <Message.Header>Rebuild this texture if you've changed channels outside this group...</Message.Header>
                                        <Message.Content>After the texture has been rebuilt, it may take several seconds before it reloads.</Message.Content>
                                    </Message>

                                    <Button onClick={onRebuildChannelGroup.bind(this)}>Rebuild Unity Texture</Button>

                                    <Segment basic loading={this.state.imageLoading}>
                                        {(this.state.imageLoading === false && this.state.currentChannelGroup.textures[0] && this.state.currentChannelGroup.textures[0].url) && <Image src={this.state.currentChannelGroup.textures[0].url} size='medium' bordered />}
                                    </Segment>
                                </Grid.Column>
                            </Grid.Row>
                        </Grid>
                    )}
                    <Form.Group>
                        {(!this.state.currentChannelGroup.id) && <Button primary content='Create Channel Group' type='submit' />}
                        {(this.state.currentChannelGroup.id) && <Button primary content='Save Channel Group' type='submit' />}
                    </Form.Group>
                </Form>
            </div>
        )
    }

    render() {
        let contents = null;
        let title = null;
        if (this.state.view === Views.Channels) {
            title = "Channels";
            contents = this.renderChannels();
        } else if (this.state.view === Views.ChannelGroups) {
            title = "All Channel Groups";
            contents = this.renderChannelGroups();
        } else if (this.state.view === Views.ChannelEditor) {
            title = (this.state.currentChannel.id) ? this.state.currentChannel.name : "Create Channel";
            contents = this.renderChannelEditor();
        } else if (this.state.view === Views.ChannelGroupEditor) {
            title = (this.state.currentChannelGroup.id) ? "Edit Channel Group" : "Create Channel Group";
            contents = this.renderChannelGroupEditor();
        } else if (this.state.view === Views.Loading) {
            contents = (
                <Segment loading={true}><Header>Loading...</Header></Segment>
            )
        }
        return (
            <MoviesTVWrapper title={title}>
                {contents}
            </MoviesTVWrapper>
        );
    }
}

export default TVDashboard;
