/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
import React from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import PropTypes from 'prop-types';
import Icons from 'src/components/Icons';
import { styled, t } from '@superset-ui/core';
import { Tooltip } from 'src/components/Tooltip';
import ReportModal from 'src/components/ReportModal';
import {
  fetchUISpecificReport,
  toggleActive,
  deleteActiveReport,
} from 'src/reports/actions/reports';
import { isFeatureEnabled, FeatureFlag } from 'src/featureFlags';
import HeaderReportActionsDropdown from 'src/components/ReportModal/HeaderReportActionsDropdown';
import { chartPropShape } from '../../dashboard/util/propShapes';
import ExploreActionButtons from './ExploreActionButtons';
import RowCountLabel from './RowCountLabel';
import EditableTitle from '../../components/EditableTitle';
import AlteredSliceTag from '../../components/AlteredSliceTag';
import FaveStar from '../../components/FaveStar';
import Timer from '../../components/Timer';
import CachedLabel from '../../components/CachedLabel';
import PropertiesModal from './PropertiesModal';
import { sliceUpdated } from '../actions/exploreActions';

const CHART_STATUS_MAP = {
  failed: 'danger',
  loading: 'warning',
  success: 'success',
};

const propTypes = {
  actions: PropTypes.object.isRequired,
  addHistory: PropTypes.func,
  can_overwrite: PropTypes.bool.isRequired,
  can_download: PropTypes.bool.isRequired,
  isStarred: PropTypes.bool.isRequired,
  slice: PropTypes.object,
  sliceName: PropTypes.string,
  table_name: PropTypes.string,
  form_data: PropTypes.object,
  ownState: PropTypes.object,
  timeout: PropTypes.number,
  chart: chartPropShape,
};

const StyledHeader = styled.div`
  display: flex;
  flex-direction: row;
  align-items: center;
  flex-wrap: wrap;
  justify-content: space-between;

  span[role='button'] {
    display: flex;
    height: 100%;
  }

  .title-panel {
    display: flex;
    align-items: center;
  }

  .right-button-panel {
    display: flex;
    align-items: center;

    > .btn-group {
      flex: 0 0 auto;
      margin-left: ${({ theme }) => theme.gridUnit}px;
    }
  }

  .action-button {
    color: ${({ theme }) => theme.colors.grayscale.base};
    margin: 0 ${({ theme }) => theme.gridUnit * 1.5}px 0
      ${({ theme }) => theme.gridUnit}px;
  }
`;

const StyledButtons = styled.span`
  display: flex;
  align-items: center;
`;

export class ExploreChartHeader extends React.PureComponent {
  constructor(props) {
    super(props);
    this.state = {
      isPropertiesModalOpen: false,
      showingReportModal: false,
    };
    this.openPropertiesModal = this.openPropertiesModal.bind(this);
    this.closePropertiesModal = this.closePropertiesModal.bind(this);
    this.showReportModal = this.showReportModal.bind(this);
    this.hideReportModal = this.hideReportModal.bind(this);
    this.renderReportModal = this.renderReportModal.bind(this);
  }

  componentDidMount() {
    if (this.canAddReports()) {
      const { user, chart } = this.props;
      // this is in the case that there is an anonymous user.
      this.props.fetchUISpecificReport(
        user.userId,
        'chart_id',
        'charts',
        chart.id,
      );
    }
  }

  getSliceName() {
    return this.props.sliceName || t('%s - untitled', this.props.table_name);
  }

  postChartFormData() {
    this.props.actions.postChartFormData(
      this.props.form_data,
      true,
      this.props.timeout,
      this.props.chart.id,
      this.props.ownState,
    );
  }

  openPropertiesModal() {
    this.setState({
      isPropertiesModalOpen: true,
    });
  }

  closePropertiesModal() {
    this.setState({
      isPropertiesModalOpen: false,
    });
  }

  showReportModal() {
    this.setState({ showingReportModal: true });
  }

  hideReportModal() {
    this.setState({ showingReportModal: false });
  }

  renderReportModal() {
    const attachedReportExists = !!Object.keys(this.props.reports).length;
    return attachedReportExists ? (
      <HeaderReportActionsDropdown
        showReportModal={this.showReportModal}
        hideReportModal={this.hideReportModal}
        toggleActive={this.props.toggleActive}
        deleteActiveReport={this.props.deleteActiveReport}
      />
    ) : (
      <>
        <span
          role="button"
          title={t('Schedule email report')}
          tabIndex={0}
          className="action-button"
          onClick={this.showReportModal}
        >
          <Icons.Calendar />
        </span>
      </>
    );
  }

  canAddReports() {
    if (!isFeatureEnabled(FeatureFlag.ALERT_REPORTS)) {
      return false;
    }
    const { user } = this.props;
    if (!user) {
      // this is in the case that there is an anonymous user.
      return false;
    }
    const roles = Object.keys(user.roles || []);
    const permissions = roles.map(key =>
      user.roles[key].filter(
        perms => perms[0] === 'menu_access' && perms[1] === 'Manage',
      ),
    );
    return permissions[0].length > 0;
  }

  render() {
    const { user, form_data: formData } = this.props;
    const {
      chartStatus,
      chartUpdateEndTime,
      chartUpdateStartTime,
      latestQueryFormData,
      queriesResponse,
    } = this.props.chart;
    // TODO: when will get appropriate design for multi queries use all results and not first only
    const queryResponse = queriesResponse?.[0];
    const chartFinished = ['failed', 'rendered', 'success'].includes(
      this.props.chart.chartStatus,
    );
    return (
      <StyledHeader id="slice-header" className="panel-title-large">
        <div className="title-panel">
          <EditableTitle
            title={this.getSliceName()}
            canEdit={!this.props.slice || this.props.can_overwrite}
            onSaveTitle={this.props.actions.updateChartTitle}
          />

          {this.props.slice && (
            <StyledButtons>
              {user.userId && (
                <FaveStar
                  itemId={this.props.slice.slice_id}
                  fetchFaveStar={this.props.actions.fetchFaveStar}
                  saveFaveStar={this.props.actions.saveFaveStar}
                  isStarred={this.props.isStarred}
                  showTooltip
                />
              )}
              <PropertiesModal
                show={this.state.isPropertiesModalOpen}
                onHide={this.closePropertiesModal}
                onSave={this.props.sliceUpdated}
                slice={this.props.slice}
              />
              <Tooltip
                id="edit-desc-tooltip"
                title={t('Edit chart properties')}
              >
                <span
                  role="button"
                  tabIndex={0}
                  className="edit-desc-icon"
                  onClick={this.openPropertiesModal}
                >
                  <i className="fa fa-edit" />
                </span>
              </Tooltip>
              {this.props.chart.sliceFormData && (
                <AlteredSliceTag
                  className="altered"
                  origFormData={this.props.chart.sliceFormData}
                  currentFormData={formData}
                />
              )}
            </StyledButtons>
          )}
        </div>
        <div className="right-button-panel">
          {chartFinished && queryResponse && (
            <RowCountLabel
              rowcount={Number(queryResponse.rowcount) || 0}
              limit={Number(formData.row_limit) || 0}
            />
          )}
          {chartFinished && queryResponse && queryResponse.is_cached && (
            <CachedLabel
              onClick={this.postChartFormData.bind(this)}
              cachedTimestamp={queryResponse.cached_dttm}
            />
          )}
          <Timer
            startTime={chartUpdateStartTime}
            endTime={chartUpdateEndTime}
            isRunning={chartStatus === 'loading'}
            status={CHART_STATUS_MAP[chartStatus]}
          />
          {this.canAddReports() && this.renderReportModal()}
          <ReportModal
            show={this.state.showingReportModal}
            onHide={this.hideReportModal}
            props={{
              userId: this.props.user.userId,
              userEmail: this.props.user.email,
              chart: this.props.chart,
              creationMethod: 'charts',
            }}
          />
          <ExploreActionButtons
            actions={{
              ...this.props.actions,
              openPropertiesModal: this.openPropertiesModal,
            }}
            slice={this.props.slice}
            canDownloadCSV={this.props.can_download}
            chartStatus={chartStatus}
            latestQueryFormData={latestQueryFormData}
            queryResponse={queryResponse}
          />
        </div>
      </StyledHeader>
    );
  }
}

ExploreChartHeader.propTypes = propTypes;

function mapDispatchToProps(dispatch) {
  return bindActionCreators(
    { sliceUpdated, fetchUISpecificReport, toggleActive, deleteActiveReport },
    dispatch,
  );
}

export default connect(null, mapDispatchToProps)(ExploreChartHeader);
