import { Direction, Directionality } from '@angular/cdk/bidi';
import { DOCUMENT } from '@angular/common';
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Inject, NgZone, OnDestroy, OnInit, Optional } from '@angular/core';
import { copy, LazyService } from '@delon/util';
import { NzMessageService } from 'ng-zorro-antd/message';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';

import { BrandService } from '../pro.service';
import { ProLayout } from '../pro.types';

@Component({
  selector: 'pro-setting-drawer',
  templateUrl: './setting-drawer.component.html',
  preserveWhitespaces: false,
  host: {
    '[class.setting-drawer]': 'true',
    '[class.setting-drawer-rtl]': `dir === 'rtl'`
  },
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class ProSettingDrawerComponent implements OnInit, OnDestroy {
  private loadedLess = false;
  private destroy$ = new Subject<void>();

  get layout(): ProLayout {
    return this.brand.layout;
  }

  collapse = false;
  dir: Direction = 'ltr';

  themes = [
    {
      key: 'dark',
      title: '暗色菜单风格',
      img: 'https://gw.alipayobjects.com/zos/rmsportal/LCkqqYNmvBEbokSDscrm.svg'
    },
    {
      key: 'light',
      title: '亮色菜单风格',
      img: 'https://gw.alipayobjects.com/zos/rmsportal/jpRkZQMyYRryryPNtyIC.svg'
    }
  ];

  color = '#2F54EB';
  colors = [
    {
      key: '薄暮',
      color: '#F5222D'
    },
    {
      key: '火山',
      color: '#FA541C'
    },
    {
      key: '日暮',
      color: '#FAAD14'
    },
    {
      key: '明青',
      color: '#13C2C2'
    },
    {
      key: '极光绿',
      color: '#52C41A'
    },
    {
      key: '拂晓蓝（默认）',
      color: '#1890ff'
    },
    {
      key: '极客蓝',
      color: '#2F54EB'
    },
    {
      key: '酱紫',
      color: '#722ED1'
    }
  ];

  menuModes = [
    {
      key: 'side',
      title: '侧边菜单布局',
      img: 'https://gw.alipayobjects.com/zos/rmsportal/JopDzEhOqwOjeNTXkoje.svg'
    },
    {
      key: 'top',
      title: '顶部菜单布局',
      img: 'https://gw.alipayobjects.com/zos/rmsportal/KDNDBbriJhLwuqMoxcAr.svg'
    }
  ];

  contentWidths = [
    {
      key: 'fixed',
      title: '定宽',
      disabled: false
    },
    {
      key: 'fluid',
      title: '流式',
      disabled: false
    }
  ];

  constructor(
    public brand: BrandService,
    private cdr: ChangeDetectorRef,
    private msg: NzMessageService,
    private lazy: LazyService,
    private zone: NgZone,
    @Inject(DOCUMENT) private doc: any,
    @Optional() private directionality: Directionality
  ) {
    this.setLayout('menu', this.brand.menu, false);
  }

  ngOnInit(): void {
    this.dir = this.directionality.value;
    this.directionality.change?.pipe(takeUntil(this.destroy$)).subscribe((direction: Direction) => {
      this.dir = direction;
      this.cdr.detectChanges();
    });
  }

  ngOnDestroy(): void {
    this.destroy$.next();
    this.destroy$.complete();
  }

  private loadLess(): Promise<void> {
    if (this.loadedLess) {
      return Promise.resolve();
    }
    return this.lazy
      .loadStyle('./assets/color.less', 'stylesheet/less')
      .then(() => {
        const lessConfigNode = this.doc.createElement('script');
        lessConfigNode.innerHTML = `
          window.less = {
            async: true,
            env: 'production',
            javascriptEnabled: true
          };
        `;
        this.doc.body.appendChild(lessConfigNode);
      })
      .then(() => this.lazy.loadScript('https://gw.alipayobjects.com/os/lib/less.js/3.8.1/less.min.js'))
      .then(() => {
        this.loadedLess = true;
      });
  }

  private runLess(): void {
    const { color, zone, msg, cdr: cd } = this;
    const msgId = msg.loading(`正在编译主题！`, { nzDuration: 0 }).messageId;
    setTimeout(() => {
      zone.runOutsideAngular(() => {
        this.loadLess().then(() => {
          (window as any).less
            .modifyVars({
              [`@primary-color`]: color
            })
            .then(() => {
              msg.success('成功');
              msg.remove(msgId);
              zone.run(() => cd.detectChanges());
            });
        });
      });
    }, 200);
  }

  toggle(): void {
    this.collapse = !this.collapse;
  }

  changeColor(color: string): void {
    this.color = color;
    this.runLess();
  }

  setLayout(name: string, value: any, cd: boolean = true): void {
    switch (name) {
      case 'menu':
        const isTop = value === 'top';
        this.contentWidths.find(w => w.key === 'fixed')!.disabled = !isTop;
        const newLayout = {
          ...this.brand.layout,
          contentWidth: isTop ? 'fixed' : 'fluid',
          onlyIcon: isTop,
          collapsed: isTop && !this.brand.isMobile ? false : this.brand.layout.collapsed
        };
        this.brand.setLayout(newLayout);
        break;
      case 'fixedHeader':
        this.brand.setLayout('autoHideHeader', false);
        break;
      default:
        break;
    }
    this.brand.setLayout(name, value);
    if (cd) {
      setTimeout(() => {
        // Re-render G2 muse be trigger window resize
        window.dispatchEvent(new Event('resize'));
        this.cdr.markForCheck();
      });
    }
  }

  copy(): void {
    const { color, layout } = this;
    const vars: { [key: string]: string } = {
      [`@primary-color`]: color
    };
    const colorVars = Object.keys(vars)
      .map(key => `${key}: ${vars[key]};`)
      .join('\n');
    const layoutVars = Object.keys(layout)
      .filter(
        key => ~['theme', 'menu', 'contentWidth', 'fixedHeader', 'autoHideHeader', 'fixSiderbar', 'colorWeak', 'onlyIcon'].indexOf(key)
      )
      .map(key => {
        const value = layout[key];
        if (typeof value === 'boolean') {
          return `    ${key}: ${value},`;
        } else {
          return `    ${key}: '${value}',`;
        }
      })
      .join('\n');
    copy(
      `在 [src/styles/theme.less] 配置以下：\n{{colorVars}}\n\n在 [src/environments/*] 的 pro 配置以下：\nexport const environment = {\n  ...\n  pro: {\n{{layoutVars}}\n  }\n}`
    );
    this.msg.success(`拷贝成功，请根据剪切板内容进行替换`);
  }
}
