import isNull from 'lodash/isNull';
import isUndefined from 'lodash/isUndefined';
import React from 'react';

import {DashboardsContext} from '../context';
import {ServiceState, lookupService} from '../lib';

export class ServiceContainer extends React.Component {
  constructor (props) {
    super(props);
    this.serviceUnsubscribe = null;

    this.state = {
      serviceState: null,
      showSettingsModal: false,
      nextCharacteristics: null,
    };
  }
  service = () => {
    return lookupService(
      this.context.dashboards, this.props.kind, this.props.instance
    );
  }
  setServiceState = (payload, {reset}) => {
    let nextServiceState = null;
    if (reset || isNull(this.state.serviceState)) {
      nextServiceState = new ServiceState(payload);
    } else {
      nextServiceState = this.state.serviceState.update(payload);
    }

    this.setState({serviceState: nextServiceState});
  }
  setNextCharacteristics = (nextCharacteristics) => {
    this.setState({nextCharacteristics: nextCharacteristics});
  }
  setNextCharacteristicsFromService = (fromService) => {
    let nextCharacteristics = null;
    if (fromService && this.service().widgetComponent && !fromService.isDummy()) {
      nextCharacteristics = {...fromService.characteristics};
    }

    this.setState({nextCharacteristics: nextCharacteristics});
  }
  showHideSettingsModal = (show) => {
    if (show) {
      this.setNextCharacteristicsFromService(this.service());
    } else {
      this.setNextCharacteristicsFromService(null);
    }

    this.setState({showSettingsModal: show});
  }
  onSettingsButtonClick = () => {
    this.showHideSettingsModal(true);
  }
  onSettingsModalClose = () => {
    this.showHideSettingsModal(false);
  }
  onSettingsModalSaveButtonClick = () => {
    this.context.saveServiceCharacteristics(
      this.props.kind, this.props.instance, this.state.nextCharacteristics
    );
    this.onSettingsModalClose();
  }
  onSettingsModalNukeButtonClick = () => {
    this.context.nukeService(this.props.kind, this.props.instance);
    this.onSettingsModalClose();
  }
  onAppearancePopupColorChange = (color) => {
    const currentCharacteristics = this.service().characteristics;
    this.context.saveServiceCharacteristics(
      this.props.kind, this.props.instance, {
        ...currentCharacteristics,
        appearance: {
          ...(currentCharacteristics.appearance || {}),
          color: color,
        },
      }
    );
  }
  onServiceRestartButtonClick = () => {
    this.service().restart();
  }
  unsubscribeIfNeeded = () => {
    if (!isNull(this.serviceUnsubscribe)) {
      this.serviceUnsubscribe();
    }
  }
  componentDidMount () {
    const service = this.service();
    if (service && service.widgetComponent && !service.isDummy()) {
      this.setServiceState(service.initialState(), true);
      service.start();

      this.unsubscribeIfNeeded();
      this.serviceUnsubscribe = service.subscribe(this.setServiceState);
    }
  }
  componentWillUnmount () {
    this.unsubscribeIfNeeded();
  }
  render () {
    const WidgetComponent = this.service().widgetComponent;

    const hasSettingsView = Boolean(
      !this.service().isDummy()
      && WidgetComponent
      && !isUndefined(WidgetComponent.settingsView)
    );

    const settingsViewProps = {
      kind: this.props.kind,
      instance: this.props.instance,
      nextCharacteristics: this.state.nextCharacteristics,
      setNextCharacteristics: this.setNextCharacteristics,
    };

    return this.props.children({
      hasSettingsView: hasSettingsView,
      service: this.service(),
      serviceState: this.state.serviceState,
      setServiceState: this.setServiceState,
      settingsViewProps: settingsViewProps,
      showSettingsModal: this.state.showSettingsModal,
      onAppearancePopupColorChange: this.onAppearancePopupColorChange,
      onServiceRestartButtonClick: this.onServiceRestartButtonClick,
      onSettingsButtonClick: this.onSettingsButtonClick,
      onSettingsModalClose: this.onSettingsModalClose,
      onSettingsModalNukeButtonClick: this.onSettingsModalNukeButtonClick,
      onSettingsModalSaveButtonClick: this.onSettingsModalSaveButtonClick,
    });
  }
}

ServiceContainer.contextType = DashboardsContext;
