import React from 'react';
import { History, RouteHandler } from 'react-router';
import { routeActions } from 'redux-simple-router';
import Immutable from 'immutable';
import ReactDOM from 'react-dom';
import reactMixin from 'react-mixin';
import { connect } from 'react-redux';
import store from 'store';
import { addPopout, removePopout } from 'actions/popouts';
import { saveLayout } from 'actions/workspaces';

import { quoteService, feedService, channelService } from 'services';
import { IS_BETA_USER, CAN_ACCESS_BZPRO } from 'utils/session';

import WidgetContainer from '../widgets/WidgetContainer';
import ConnectionStatus from 'utils/ConnectionStatus';
import SiteHeader from '../SiteHeader';
import WorkspaceNav from '../dashboard/workspace/WorkspaceNav';
import SidebarNav from '../SidebarNav';
import Workspace from '../dashboard/workspace/Workspace';
import Tutorials from '../tutorials/Tutorials';
import Ticker from 'components/ui/Ticker';
import Preloader from 'components/ui/Preloader';
import AlertAudio from 'utils/AlertAudio';

// A route handler that represents the Dashboard route.
class Dashboard extends React.Component {
  constructor(...args) {
    super(...args);

    // HACK: Don't do this. Need proper loading for services. If we don't do
    // this, adding a feed widget early (i.e. from saved workspaces) will
    // crash the app.
    this.state = {
      isLoading: true,
      openPopouts: {},
    };
  }

  componentWillMount() {
    // handle page exit and refresh
    window.onbeforeunload = () => saveLayout();

    const { session } = this.props;
    this.redirectUser(session);
  }

  componentDidMount() {
    window.addEventListener('popout', this.handlePopoutEvent);

    channelService.connect();
    quoteService.connect();
    feedService.connect();

    // HACK: Don't do this.
    this.state.isLoading = false;
    this.forceUpdate();

    this.renderPopouts(this.props.popouts);
  }

  componentWillReceiveProps(nextProps) {
    const { popouts, session } = nextProps;

    if (this.props.popouts !== popouts) {
      this.renderPopouts(popouts);
    }
    this.redirectUser(session);
  }

  componentWillUnmount() {
    window.removeEventListener('popout', this.handlePopoutEvent);
  }

  handlePopoutEvent(e) {
    const { type, data } = e.originalEvent;
    const { dispatch } = this.props;
    dispatch(addPopout(type, data));
  }

  redirectUser(session) {
    const { dispatch } = this.props;
    const redirect = next => {
      return dispatch(routeActions.replace(next));
    };

    // So lame...
    if (session.isLoggedIn !== null) {
      if (!session.isLoggedIn) {
        return redirect('/login/');
      }
      if (!session.hasPerm(CAN_ACCESS_BZPRO)) {
        if (session.hasPerm(IS_BETA_USER)) {
          return redirect('/pricing/?modal=beta_has_ended');
        }
        return redirect('/pricing/');
      }
    }
  }

  renderPopouts(popouts) {
    const { openPopouts } = this.state;
    const pops = popouts.toJS();
    const options = 'width=750,height=700,left=0,resizable';
    const openWindow = (url, name) => {
      openPopouts[name] = window.open(url, name, options);
      return openPopouts[name];
    };
    const findWindow = (name) => {
      return openPopouts[name];
    };

    if (pops.length > 0) {
      pops.map((popout) => {
        const { id, type, data } = popout;
        if (!findWindow(id)) {
          const encodedData = encodeURIComponent(JSON.stringify(data));
          openWindow('/popout/?i=' + id + '&t=' + type + '&d=' + encodedData, id, options);

          // Remove window object reference on window close
          findWindow(id).onbeforeunload = () => {
            this.props.dispatch(removePopout(id));
          };
        }
      });
    }
  }

  render() {
    const { activeWorkspace, workspaces, activeWorkspaceIndex, tutorials, watchlists } = this.props;
    // const activeTutorial = tutorials.filter(tutorial => !tutorial.get('completed')).take(1);
    const activeTutorial = null;

    if (this.state.isLoading || watchlists.get('isLoading')) {
      return (<main role="application"><Preloader percent={75} /></main>);
    }

    return (
      <main role="application">
        <ConnectionStatus />
        <AlertAudio />
        {activeTutorial ? <Tutorials tutorials={tutorials} activeTutorial={activeTutorial} /> : null}
        <SidebarNav />
        <WorkspaceNav workspaces={workspaces} activeWorkspaceIndex={activeWorkspaceIndex} />
        {workspaces.map((ws, index) =>
          <Workspace
            activeWorkspace={ws}
            visible={index === activeWorkspaceIndex}
            tutorials={tutorials}
            key={index}
          />
        )}
      </main>
    );
  }
}

function selectWorkspace(state) {
  return {
    activeWorkspaceIndex: state.workspaces.get('activeWorkspace'),
    workspaces: state.workspaces.get('workspaceList'),
    activeWorkspace: state.workspaces.getIn(['workspaceList', state.workspaces.get('activeWorkspace')]),
    tutorials: state.tutorials,
    popouts: state.popouts,
    watchlists: state.watchlists,
  };
}

Dashboard.propTypes = {
  dispatch: React.PropTypes.func.isRequired,
  activeWorkspace: React.PropTypes.object.isRequired,
  workspaces: React.PropTypes.object.isRequired,
  activeWorkspaceIndex: React.PropTypes.number.isRequired,
  tutorials: React.PropTypes.object.isRequired,
  session: React.PropTypes.object.isRequired,
  popouts: React.PropTypes.object,
  watchlists: React.PropTypes.object,
  location: React.PropTypes.object.isRequired,
};

export default connect(selectWorkspace)(Dashboard);
