import rpc from '../rpc';
import isUrl from '../utils/url-command';
import {keys} from '../utils/object';
import findBySession from '../utils/term-groups';
import {
  SESSION_ADD,
  SESSION_RESIZE,
  SESSION_REQUEST,
  SESSION_ADD_DATA,
  SESSION_PTY_DATA,
  SESSION_PTY_EXIT,
  SESSION_USER_EXIT,
  SESSION_SET_ACTIVE,
  SESSION_CLEAR_ACTIVE,
  SESSION_USER_DATA,
  SESSION_URL_SET,
  SESSION_URL_UNSET,
  SESSION_SET_XTERM_TITLE
} from '../constants/sessions';

export function addSession({uid, shell, pid, cols, rows, splitDirection}) {
  return (dispatch, getState) => {
    const {sessions} = getState();
    dispatch({
      type: SESSION_ADD,
      uid,
      shell,
      pid,
      cols,
      rows,
      splitDirection,
      activeUid: sessions.activeUid
    });
  };
}

export function requestSession() {
  return (dispatch, getState) => {
    const {ui} = getState();
    const {cols, rows, cwd} = ui;
    dispatch({
      type: SESSION_REQUEST,
      effect: () => {
        rpc.emit('new', {cols, rows, cwd});
      }
    });
  };
}

export function addSessionData(uid, data) {
  return function (dispatch, getState) {
    dispatch({
      type: SESSION_ADD_DATA,
      data,
      effect() {
        const session = getState().sessions.sessions[uid];
        if (session) {
          const enterKey = data.indexOf('\n') > 0;
          const url = enterKey ? isUrl(session.shell, data) : null;
          if (url) {
            return dispatch({
              type: SESSION_URL_SET,
              uid,
              url
            });
          }
        }
        dispatch({
          type: SESSION_PTY_DATA,
          uid,
          data
        });
      }
    });
  };
}

function createExitAction(type) {
  return uid => (dispatch, getState) => {
    return dispatch({
      type,
      uid,
      effect() {
        if (type === SESSION_USER_EXIT) {
          rpc.emit('exit', {uid});
        }

        const sessions = keys(getState().sessions.sessions);
        if (sessions.length === 0) {
          window.close();
        }
      }
    });
  };
}

// we want to distinguish an exit
// that's UI initiated vs pty initiated
export const userExitSession = createExitAction(SESSION_USER_EXIT);
export const ptyExitSession = createExitAction(SESSION_PTY_EXIT);

export function setActiveSession(uid) {
  return dispatch => {
    dispatch({
      type: SESSION_SET_ACTIVE,
      uid
    });
  };
}

export function clearActiveSession() {
  return {
    type: SESSION_CLEAR_ACTIVE
  };
}

export function setSessionXtermTitle(uid, title) {
  return {
    type: SESSION_SET_XTERM_TITLE,
    uid,
    title
  };
}

export function resizeSession(uid, cols, rows) {
  return (dispatch, getState) => {
    const {termGroups} = getState();
    const group = findBySession(termGroups, uid);
    const isStandaloneTerm = !group.parentUid && !group.children.length;
    dispatch({
      type: SESSION_RESIZE,
      uid,
      cols,
      rows,
      isStandaloneTerm,
      effect() {
        rpc.emit('resize', {uid, cols, rows});
      }
    });
  };
}

export function sendSessionData(uid, data, escaped) {
  return function (dispatch, getState) {
    dispatch({
      type: SESSION_USER_DATA,
      data,
      effect() {
        // If no uid is passed, data is sent to the active session.
        const targetUid = uid || getState().sessions.activeUid;

        rpc.emit('data', {uid: targetUid, data, escaped});
      }
    });
  };
}

export function exitSessionBrowser(uid) {
  return {
    type: SESSION_URL_UNSET,
    uid
  };
}
