import React from 'react';
import NotFound from '../../src/components/404';
import Layout from '../../src/components/Layout';
import AsideNav from '../../src/components/AsideNav';
import {
  AlertComponent,
  Button,
  Drawer,
  ToastComponent
} from '../../src/components/index';
import {eachTree, mapTree} from '../../src/utils/helper';
import {Icon} from '../../src/components/icons';
import '../../src/locale/en-US';
import {
  Router,
  Route,
  IndexRoute,
  browserHistory,
  hashHistory,
  Link,
  Redirect,
  withRouter
} from 'react-router';
import Select from '../../src/components/Select';
import DocSearch from './DocSearch';
import Doc from './Doc';
import DocNavCN from './DocNavCN';
import Example, {examples} from './Example';
import CssDocs, {cssDocs} from './CssDocs';
import CSSDocs from './CssDocs';

declare const _hmt: any;

let ExamplePathPrefix = '/examples';
let DocPathPrefix = '/docs';
let ContextPath = '';

if (process.env.NODE_ENV === 'production') {
  ExamplePathPrefix = '';
  DocPathPrefix = '';
  ContextPath = '/amis';
}

export function getContextPath() {
  return ContextPath;
}

const themes = [
  {
    label: '默认主题',
    ns: 'a-',
    value: 'default'
  },

  {
    label: '百度云舍',
    ns: 'cxd-',
    value: 'cxd'
  },
  {
    label: 'Dark',
    ns: 'dark-',
    value: 'dark'
  },
  {
    label: '仿 AntD',
    ns: 'antd-',
    value: 'antd'
  }
];

const locales = [
  {
    label: '中文',
    value: 'zh-CN'
  },

  {
    label: 'English',
    value: 'en-US'
  }
];

const viewModes = [
  {
    label: '桌面端',
    value: 'pc'
  },

  {
    label: '移动端',
    value: 'mobile'
  }
];

function getPath(path) {
  return path
    ? path[0] === '/'
      ? ContextPath + path
      : `${ContextPath}/${path}`
    : '';
}

class BackTop extends React.PureComponent {
  state = {
    show: false
  };

  componentDidMount() {
    document.addEventListener('scroll', this.handleScroll.bind(this));
  }

  componentWillUnmount() {
    document.removeEventListener('scroll', this.handleScroll.bind(this));
  }

  handleScroll(e) {
    this.setState({
      show: e.target.scrollingElement?.scrollTop > 350
    });
  }

  render() {
    return (
      <div
        className={`Backtop ${this.state.show ? 'visible' : ''}`}
        onClick={() => scrollTo({top: 0})}
      >
        <i className="fa fa-rocket"></i>
      </div>
    );
  }
}
// @ts-ignore
@withRouter // @ts-ignore
export class App extends React.PureComponent<{
  location: Location;
}> {
  state = {
    viewMode: localStorage.getItem('viewMode') || 'pc',
    offScreen: false,
    folded: false,
    headerVisible: true,
    themeIndex: 0,
    themes: themes,
    theme:
      themes.find(item => item?.value === localStorage.getItem('theme')) ||
      themes[0],
    locale: localStorage.getItem('locale')
      ? localStorage.getItem('locale').replace('zh-cn', 'zh-CN')
      : '',
    navigations: []
  };

  constructor(props) {
    super(props);
    this.setNavigations = this.setNavigations.bind(this);
  }

  componentDidUpdate(preProps, preState) {
    const props = this.props;

    if (preState.theme.value !== this.state.theme.value) {
      [].slice
        .call(document.querySelectorAll('link[title]'))
        .forEach((item: HTMLLinkElement) => {
          const theme = item.getAttribute('title');
          item.disabled = theme !== this.state.theme.value;
        });
      const body = document.querySelector('body');
      body.classList.remove(preState.theme.value);
      body.classList.add(this.state.theme.value);
    }

    if (props.location.pathname !== preProps.location.pathname) {
      this.setState(
        {
          offScreen: false
        },
        () => window.scrollTo(0, 0)
      );

      _hmt && _hmt.push(['_trackPageview', props.location.pathname]);
    }
  }

  setNavigations(items) {
    this.setState({
      navigations: items
    });
  }

  renderHeader(docPage = true) {
    const location = this.props.location;
    const theme = this.state.theme;

    if (location.pathname === '/edit') {
      return (
        <div id="headerBar" className="box-shadow bg-dark">
          <div className={`${theme.ns}Layout-brand`}>AMis 可视化编辑器</div>
        </div>
      );
    }

    return (
      <>
        <div
          className={`${theme.ns}Layout-brandBar ${
            docPage ? 'DocLayout-brandBar' : ''
          }`}
        >
          <div
            onClick={() => this.setState({offScreen: !this.state.offScreen})}
            className={`${theme.ns}Layout-offScreen-btn ${
              docPage ? 'DocLayout-offScreen-btn' : ''
            } pull-right visible-xs`}
          >
            <i className="bui-icon iconfont icon-collapse"></i>
          </div>

          {docPage ? (
            <div
              className={`${theme.ns}Layout-brand  ${
                docPage ? 'DocLayout-brand' : ''
              }`}
            >
              <Link to={`${ContextPath}/docs`}>
                <div className="logo"></div>
              </Link>
            </div>
          ) : (
            <div className={`${theme.ns}Layout-brand text-ellipsis`}>
              <i className="fa fa-paw" />
              <span className="hidden-folded m-l-sm">AMIS 示例</span>
            </div>
          )}
        </div>

        <div
          className={`${theme.ns}Layout-headerBar ${
            docPage ? 'DocLayout-headerBar' : ''
          } pc:flex items-center`}
        >
          {docPage ? null : (
            <Button
              onClick={() => this.setState({folded: !this.state.folded})}
              type="button"
              level="link"
              className="navbar-btn"
            >
              <i
                className={`fa fa-${
                  this.state.folded ? 'indent' : 'dedent'
                } fa-fw`}
              ></i>
            </Button>
          )}

          <ul className={`HeaderLinks`}>
            <Link to={`${ContextPath}/zh-CN/docs`} activeClassName="is-active">
              文档
            </Link>
            <Link to={`${ContextPath}/style`} activeClassName="is-active">
              样式
            </Link>
            <Link to={`${ContextPath}/examples`} activeClassName="is-active">
              示例
            </Link>
            <a
              href="https://github.com/fex-team/amis-editor-demo"
              target="_blank"
            >
              可视化编辑器
            </a>
            {/* <a href="https://suda.bce.baidu.com" target="_blank">
              爱速搭
            </a> */}
          </ul>

          <div className="hidden-xs ml-auto">
            <Select
              clearable={false}
              theme={this.state.theme.value}
              value={this.state.locale || 'zh-CN'}
              options={locales}
              onChange={locale => {
                this.setState({locale: locale.value});
                localStorage.setItem('locale', locale.value);
                window.location.reload();
              }}
            />
          </div>

          <div className="hidden-xs ml-2">
            <Select
              clearable={false}
              theme={this.state.theme.value}
              value={this.state.theme}
              options={this.state.themes}
              onChange={theme => {
                this.setState({theme});
                localStorage.setItem('theme', `${theme.value}`);
                document
                  .querySelector('body')
                  .classList[theme.value === 'dark' ? 'add' : 'remove']('dark');
              }}
            />
          </div>

          <div className="hidden-xs ml-2">
            <Select
              clearable={false}
              theme={this.state.theme.value}
              value={this.state.viewMode || 'pc'}
              options={viewModes}
              onChange={viewMode => {
                this.setState({viewMode: viewMode.value});
                localStorage.setItem('viewMode', viewMode.value);
                window.location.reload();
              }}
            />
          </div>

          <div id="Header-toolbar"></div>
        </div>

        {docPage ? (
          <>
            <div
              className={`${theme.ns}Layout-searchBar ${
                docPage ? 'DocLayout-searchBar' : ''
              } hidden-xs hidden-sm`}
            >
              <DocSearch theme={theme} />
            </div>
            <a
              className="gh-icon"
              href="https://github.com/baidu/amis"
              target="_blank"
            >
              <i className="fa fa-github" />
            </a>
          </>
        ) : null}
      </>
    );
  }

  renderNavigation() {
    return <div className="Doc-navigation">{this.renderAsideNav()}</div>;
  }

  renderAsideNav() {
    return (
      <AsideNav
        navigations={this.state.navigations.map(item => ({
          ...item,
          children: item.children
            ? item.children.map(item => ({
                ...item,
                className: 'is-top'
              }))
            : []
        }))}
        renderLink={({
          link,
          active,
          toggleExpand,
          classnames: cx,
          depth
        }: any) => {
          let children = [];

          if (link.children && link.children.length) {
            children.push(
              <span
                key="expand-toggle"
                className={cx('AsideNav-itemArrow')}
                onClick={e => toggleExpand(link, e)}
              ></span>
            );
          }

          link.badge &&
            children.push(
              <b
                key="badge"
                className={cx(
                  `AsideNav-itemBadge`,
                  link.badgeClassName || 'bg-info'
                )}
              >
                {link.badge}
              </b>
            );

          if (link.icon) {
            children.push(
              <i key="icon" className={cx(`AsideNav-itemIcon`, link.icon)} />
            );
          } else if (this.state.folded && depth === 1) {
            children.push(
              <i
                key="icon"
                className={cx(
                  `AsideNav-itemIcon`,
                  link.children ? 'fa fa-folder' : 'fa fa-info'
                )}
              />
            );
          }

          children.push(
            <span className={cx('AsideNav-itemLabel')} key="label">
              {link.label}
            </span>
          );

          return link.path ? (
            /^https?\:/.test(link.path) ? (
              <a target="_blank" href={link.path} rel="noopener">
                {children}
              </a>
            ) : (
              <Link
                to={
                  getPath(link.path) ||
                  (link.children && getPath(link.children[0].path))
                }
              >
                {children}
              </Link>
            )
          ) : (
            <a onClick={link.children ? () => toggleExpand(link) : undefined}>
              {children}
            </a>
          );
        }}
        isActive={(link: any) => isActive(link, location)}
      />
    );
  }

  renderExamples() {
    const theme = this.state.theme;

    return (
      <Layout
        theme={theme.value}
        offScreen={this.state.offScreen}
        folded={this.state.folded}
        header={this.renderHeader(false)}
        aside={this.renderAsideNav()}
      >
        <ToastComponent theme={theme.value} locale={this.state.locale} />
        <AlertComponent theme={theme.value} locale={this.state.locale} />

        {React.cloneElement(this.props.children as any, {
          key: theme.value,
          ...(this.props.children as any).props,
          setNavigations: this.setNavigations,
          theme: theme.value,
          classPrefix: theme.ns,
          viewMode: this.state.viewMode,
          locale: this.state.locale,
          offScreen: this.state.offScreen,
          ContextPath
        })}
      </Layout>
    );
  }

  render() {
    const theme = this.state.theme;
    const location = this.props.location;

    if (/examples\/jssdk/.test(location.pathname)) {
      return (
        <>
          <ToastComponent theme={theme.value} locale={this.state.locale} />
          <AlertComponent theme={theme.value} locale={this.state.locale} />
          {React.cloneElement(this.props.children as any, {
            key: theme.value,
            ...(this.props.children as any).props,
            setNavigations: this.setNavigations,
            theme: theme.value,
            classPrefix: theme.ns,
            viewMode: this.state.viewMode,
            locale: this.state.locale,
            offScreen: this.state.offScreen,
            ContextPath,
            showCode: false
          })}
        </>
      );
    } else if (/examples/.test(location.pathname)) {
      return this.renderExamples();
    }

    return (
      <Layout
        className={':DocLayout'}
        theme={theme.value}
        boxed={true}
        offScreen={this.state.offScreen}
        header={this.state.headerVisible ? this.renderHeader() : null}
        headerClassName={':DocLayout-header'}
      >
        <ToastComponent theme={theme.value} locale={this.state.locale} />
        <AlertComponent theme={theme.value} locale={this.state.locale} />

        <div className="Doc">
          <div className="Doc-nav hidden-xs hidden-sm">
            {this.renderNavigation()}
          </div>

          <Drawer
            size="xs"
            className="Doc-navDrawer"
            overlay
            closeOnOutside
            onHide={() => this.setState({offScreen: false})}
            show={this.state.offScreen}
            position="left"
          >
            {this.renderNavigation()}
          </Drawer>

          <BackTop />

          {React.cloneElement(this.props.children as any, {
            key: theme.value,
            ...(this.props.children as any).props,
            setNavigations: this.setNavigations,
            theme: theme.value,
            classPrefix: theme.ns,
            viewMode: this.state.viewMode,
            locale: this.state.locale,
            offScreen: this.state.offScreen,
            ContextPath
          })}
        </div>
      </Layout>
    );
  }
}

function isActive(link: any, location: any) {
  return !!(link.path && getPath(link.path) === location.pathname);
}

function navigations2route(pathPrefix = DocPathPrefix, navigations) {
  let routes = [];

  navigations.forEach(root => {
    root.children &&
      eachTree(root.children, (item: any) => {
        if (item.path && item.component) {
          routes.push(
            <Route
              key={routes.length + 1}
              path={
                item.path[0] === '/'
                  ? ContextPath + item.path
                  : `${ContextPath}/${item.path}`
              }
              component={item.component}
            />
          );
        } else if (item.path && item.getComponent) {
          routes.push(
            <Route
              key={routes.length + 1}
              path={
                item.path[0] === '/'
                  ? ContextPath + item.path
                  : `${ContextPath}/${item.path}`
              }
              getComponent={item.getComponent}
            />
          );
        }
      });
  });

  return routes;
}

export default function entry({pathPrefix}) {
  // PathPrefix = pathPrefix || DocPathPrefix;
  const locate = 'zh-CN'; // 暂时不支持切换，因为目前只有中文文档
  return (
    <Router history={browserHistory}>
      <Route component={App}>
        <Redirect
          from={`${ContextPath}/`}
          to={`${ContextPath}/${locate}/docs/index`}
        />
        <Redirect
          from={`${ContextPath}/docs`}
          to={`${ContextPath}/${locate}/docs/index`}
        />
        <Redirect
          from={`${ContextPath}/docs/index`}
          to={`${ContextPath}/${locate}/docs/index`}
        />
        <Redirect
          from={`${ContextPath}/docs/*`}
          to={`${ContextPath}/${locate}/docs/*`}
        />
        <Redirect
          from={`${ContextPath}/${locate}/docs`}
          to={`${ContextPath}/${locate}/docs/index`}
        />
        <Redirect
          from={`${ContextPath}/examples`}
          to={`${ContextPath}/examples/pages/simple`}
        />
        <Redirect
          from={`${ContextPath}/style`}
          to={`${ContextPath}/style/index`}
        />

        <Route path={`${ContextPath}/${locate}/docs`} component={Doc}>
          {navigations2route(DocPathPrefix, DocNavCN)}
        </Route>
        <Route path={`${ContextPath}/examples`} component={Example}>
          {navigations2route(ExamplePathPrefix, examples)}
        </Route>
        <Route path={`${ContextPath}/style`} component={CSSDocs}>
          {navigations2route(ExamplePathPrefix, cssDocs)}
        </Route>
      </Route>

      <Route path="*" component={NotFound} />
    </Router>
  );
}
