import * as React from 'react'
import { RouteComponentProps } from '@reach/router'
import {
  Row,
  Col,
  Layout,
  Tabs,
  Icon,
  Skeleton,
  Spin,
  Statistic,
} from 'antd'
import Markdown from '../../components/Markdown'
import { compose, DataValue } from 'react-apollo'
import { withPackage, withScript } from '../../graphql'
import {
  getPackage,
  getPackageVariables,
  getPackage_package,
} from '../../graphql/types/getPackage'
import * as moment from 'moment'
import { getScript, getScriptVariables } from '../../graphql/types/getScript'
import { applyScriptToPackage } from '../../helpers'
import { PackageHeader } from '../../components/PackageHeader'

import './index.less'
import CodeEditor from '../../components/CodeEditor'
import DependenciesTable from '../../components/DependenciesTable'
import PlatformTable from '../../components/PlatformTable';

export interface PackageViewScriptData {
  version: string
}

interface TimelineMetrics {
  successful: number
  failed: number
  success_rate: number
}

export interface PackageViewData {
  name: string
  namespace?: string
  category: string
  version: string
  latestVersion: string
  latestRelease: string
  description: string
}

export interface Props {
  onBack: () => void
  onClickView: () => void
  onClickDownload: () => void
  onChangeVersion: (version: string) => void
  version?: string
}

interface ChildData {
  package: DataValue<getPackage, getPackageVariables>
  script?: DataValue<getScript, getScriptVariables>
}

class PackageView extends React.Component<
  Props & RouteComponentProps & ChildData,
  any
  > {
  public render() {
    const { package: packageData, script: scriptData } = this.props

    let { loading, package: pkg } = packageData

    if (loading || !pkg || !scriptData || scriptData.loading) {
      return this.renderSkeleton()
    }

    let version: string

    if (scriptData && !scriptData.loading && scriptData.script) {
      const res = applyScriptToPackage(scriptData.script, pkg)
      version = res.version
      pkg = res.data
    }

    const {
      stats: { latestRelease },
      category,
      readme,
      name,
      namespace,
      description,
      scriptMetadata,
    }: getPackage_package = pkg

    const versions = scriptMetadata.map(m => m.version)
    const latestReleaseMoment = moment(latestRelease)
    const metrics = this.getTimelineMetrics();

    return (
      <Layout
        style={{
          marginLeft: 'auto',
          marginRight: 'auto',
          maxWidth: '900px',
        }}
      >
        <PackageHeader
          name={name}
          namespace={namespace}
          description={description}
          onBack={this.props.onBack}
          onChangeVersion={this.props.onChangeVersion}
          onClickDownload={this.props.onClickDownload}
          onClickView={this.props.onClickView}
          versions={versions}
          version={this.props.version || version}
        />
        <div className="package-view-container">
          <Row className="package-view-info">
            <Col sm={5}>
              <Statistic
                title="last publish"
                valueStyle={{ color: 'gray' }}
                value={latestReleaseMoment.fromNow()}
              />
            </Col>
            <Col sm={5}>
              <Statistic
                title="category"
                valueStyle={{ color: 'gray' }}
                value={category.toLowerCase()}
              />
            </Col>
            <Col sm={5}>
              <Statistic
                title="successful"
                value={metrics.successful}
                valueStyle={{ color: '#3f8600' }}
                suffix="Exec"
              />
            </Col>
            <Col sm={5}>
              <Statistic
                title="failed"
                value={metrics.failed}
                valueStyle={{ color: 'red' }}
                suffix="Exec"
              />
            </Col>
            <Col sm={4}>
              <Statistic
                title="success rate"
                value={metrics.success_rate}
                precision={2}
                valueStyle={{ color: this.getSuccessRateColor(metrics.success_rate) }}
                suffix="%"
              />
            </Col>
          </Row>
          <Row>
            <Col sm={24}>
              <Tabs animated={false}>
                <Tabs.TabPane
                  tab={
                    <span>
                      <Icon type="read" /> Readme
                    </span>
                  }
                  key="tab:readme"
                  className="package-tab-readme"
                >
                  <Markdown asset={readme} />
                </Tabs.TabPane>
                <Tabs.TabPane
                  tab={
                    <span>
                      <Icon type="code" /> Code
                    </span>
                  }
                  key="tab:code"
                  className="package-tab-code"
                >
                  <CodeEditor
                    readOnly={true}
                    asset={scriptData.script.execute}
                  />
                </Tabs.TabPane>
                <Tabs.TabPane
                  key="tab:dependencies"
                  className="package-tab-dependencies"
                  tab={
                    <span>
                      <Icon type="branches" /> Dependencies
                    </span>
                  }
                >
                  <DependenciesTable
                    dependencies={scriptData.script.resolvedDependencies || []}
                  />
                </Tabs.TabPane>
                <Tabs.TabPane
                  key="tab:platform"
                  className="package-tab-platform"
                  tab={
                    <span>
                      <Icon type="check-square" /> Platform Support
                    </span>
                  }
                >
                  <PlatformTable support={scriptData.script.platform} />
                </Tabs.TabPane>
              </Tabs>
            </Col>
          </Row>
        </div>
      </Layout>
    )
  }

  private renderSkeleton() {
    return (
      <Spin tip="Loading ...">
        <Layout
          style={{
            marginLeft: 'auto',
            marginRight: 'auto',
            maxWidth: '900px',
          }}
        >
          <div className="package-view-container">
            <Row>
              <Col sm={24} style={{ padding: 12 }}>
                <Skeleton paragraph={{ width: '100%', rows: 2 }} />
              </Col>
            </Row>
            <Row className="package-view-info">
              <Col sm={6}>
                <label>last publish</label>
                <Skeleton paragraph={{ width: '100%', rows: 0 }} />
              </Col>
              <Col sm={6}>
                <label>category</label>
                <Skeleton paragraph={{ width: '100%', rows: 0 }} />
              </Col>
            </Row>
            <Row>
              <Col sm={24}>
                <Tabs animated={false}>
                  <Tabs.TabPane
                    tab={
                      <span>
                        <Icon type="read" /> Readme
                      </span>
                    }
                    key="tab:readme"
                    className="package-tab-readme"
                  >
                    <Skeleton paragraph={{ width: '100%', rows: 5 }} />
                  </Tabs.TabPane>
                  <Tabs.TabPane
                    tab={
                      <span>
                        <Icon type="code" /> Code
                      </span>
                    }
                    key="tab:code"
                    className="package-tab-code"
                  />
                </Tabs>
              </Col>
            </Row>
          </div>
        </Layout>
      </Spin>
    )
  }

  private getTimelineMetrics(): TimelineMetrics {
    const { package: { package: { activitiesTimeline } } } = this.props;

    const metric = activitiesTimeline.reduce((metrics, timelineItem) => {
      metrics.successful += timelineItem.successful;
      metrics.failed += timelineItem.failed;
      return metrics;
    }, {
      failed: 0,
      successful: 0,
      success_rate: 0
    } as TimelineMetrics);

    if(!metric.failed && !metric.successful) return metric;

    metric.success_rate = (100 / (metric.failed + metric.successful)) * metric.successful;

    return metric;
  }

  private getSuccessRateColor(rate: number) {
    if(rate < 50) {
      return "red";
    } else if (rate < 60) {
      return "orange";
    } else {
      return "green";
    }
  }
}

export default compose(
  withPackage,
  withScript
)(PackageView)
