import { Component, OnDestroy, OnInit, TemplateRef, ViewChild } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { NbSidebarService, NbToastrService } from '@nebular/theme';
import { overlayConfigFactory } from 'ngx-modialog-7';
// tslint:disable-next-line: no-submodule-imports
import { Modal, VEXModalContext } from 'ngx-modialog-7/plugins/vex';
import { ResponsiveSizeInfoRx } from 'ngx-responsive';
import { Subject } from 'rxjs';
import { distinctUntilChanged, map, takeWhile, withLatestFrom } from 'rxjs/operators';
import { CombErr } from '../../@dataflow/core';
import {
	IManipulate,
	Manipulate2Icon,
	OperationsListExtendsFlowOutItemNode,
} from '../../@dataflow/extra';
import { OperationsMkdirFlow, NavigationFlowOutNode, NavigationFlow } from '../../@dataflow/rclone';
import { ConnectionService } from '../connection.service';
import { TasksQueueService } from '../tasks/tasks-queue.service';
import { ClipboardDialogComponent } from './clipboard/clipboard.dialog';
import { ClipboardService } from './clipboard/clipboard.service';
import { MkdirDialogComponent } from './dialogs/mkdir.dialog';
import { FileDetailComponent } from './fileMode/file.detail';
import { FileModeComponent } from './fileMode/fileMode.component';
import { HomeModeComponent } from './homeMode/homeMode.component';
import { RemoteDetailComponent } from './homeMode/remote.detail';

@Component({
	selector: 'app-manager',
	template: `
		<nb-layout-header subheader>
			<app-manager-breadcrumb [nav$]="nav$" (jump)="addrJump($event)"> </app-manager-breadcrumb>
			<a class="push-to-right option" (click)="refresh()"><nb-icon icon="refresh"></nb-icon></a>
			<a class="option"><nb-icon icon="list"></nb-icon></a>
			<!-- *hideItBootstrap="['xs']" -->
			<a class="option" *ngIf="pcDetailViewEnable" (click)="toggleDetail()">
				<nb-icon icon="info"></nb-icon>
			</a>
		</nb-layout-header>
		<div [ngClass]="{ subcolumn: true, 'subcolumn-right-bar': pcDetailView }">
			<nb-card>
				<nb-card-body>
					<app-manager-home-mode
						*ngIf="homeMode"
						[pcDetailView]="pcDetailView"
						(jump)="addrJump($event)"
						(showDetail)="openRemoteDetail($event)"
					>
					</app-manager-home-mode>
					<app-manager-file-mode
						*ngIf="fileMode"
						[pcDetailViewEnable]="pcDetailViewEnable"
						[nav$]="nav$"
						(jump)="addrJump($event)"
						(showDetail)="openFileDetail($event)"
					>
					</app-manager-file-mode>
				</nb-card-body>
			</nb-card>
		</div>
		<!-- *hideItBootstrap="['xs']" -->
		<nb-sidebar
			*ngIf="pcDetailViewEnable"
			fixed
			end
			class="right-bar"
			tag="detail"
			state="collapsed"
		>
			<app-home-remote-detail *ngIf="homeMode"> </app-home-remote-detail>
			<app-file-file-detail *ngIf="fileMode"> </app-file-file-detail>
		</nb-sidebar>
		<ng-template #MobileRemoteDetail let-ctx="dialogRef.context">
			<app-home-remote-detail [initNode]="ctx.navNode"> </app-home-remote-detail>
		</ng-template>
		<ng-template #MobileFileDetail let-ctx="dialogRef.context">
			<app-file-file-detail [initNode]="ctx.itemNode"> </app-file-file-detail>
		</ng-template>
		<nb-layout-footer [ngClass]="{ mobile: !mainBar, pc: mainBar }">
			<nb-actions>
				<nb-action *ngIf="fileMode" icon="copy" (click)="file.manipulate('copy')"></nb-action>
				<nb-action *ngIf="fileMode" icon="move" (click)="file.manipulate('move')"></nb-action>
				<nb-action *ngIf="fileMode" icon="trash-2" (click)="file.manipulate('del')"></nb-action>
				<nb-action *ngIf="fileMode" icon="clipboard" (click)="paste()"></nb-action>
				<nb-action *ngIf="fileMode" icon="folder-add" (click)="mkdirDialog()"></nb-action>
				<nb-action
					class="push-to-right"
					style="padding-right: 1.5rem;padding-left: 0.5rem;"
					(click)="clipboardDialog()"
				>
					<nb-icon icon="inbox" style="font-size: 1.5rem"> </nb-icon>
					<nb-badge
						*ngIf="clipboardSize"
						[text]="clipboardSize"
						status="info"
						position="top end"
					></nb-badge>
				</nb-action>
			</nb-actions>
		</nb-layout-footer>
	`,
	styles: [
		`
			nb-layout-header {
				position: sticky;
				top: 4.75rem;
				z-index: 700;
			}
			app-manager-breadcrumb {
				display: contents;
			}
			.option {
				padding: 0 0.3rem;
			}
			.right-bar {
				top: calc(4.75rem * 2 + 0.05rem) !important;
				bottom: 65px !important;
				height: auto;
				z-index: 699;
			}
			:host nb-sidebar ::ng-deep .main-container {
				height: auto !important;
				top: calc(4.75rem * 2 + 0.05rem) !important;
				bottom: 65px !important;
			}
			:host nb-sidebar ::ng-deep .scrollable {
				padding: 1.25rem 0 !important;
			}
			.subcolumn {
				margin-bottom: 4.75rem;
				margin-top: 1.5rem;
			}
			.subcolumn-right-bar {
				margin-right: 16rem;
			}
			/* nb-sidebar.right ::ng-deep .scrollable {
				padding-top: 5rem;
			} */
			nb-layout-footer {
				z-index: 998;
				position: fixed;
				bottom: 0;
			}
			nb-layout-footer.mobile {
				width: 100%;
			}
			nb-layout-footer.pc {
				width: calc(100% - 16rem);
			}
			nb-layout-footer ::ng-deep nav {
				overflow-x: auto;
			}
			nb-actions {
				width: 100%;
			}
			.push-to-right {
				margin-left: auto;
				/* margin-right: 16rem; */
			}
			.subcolumn > nb-card {
				margin: 0 1.25rem;
			}
		`,
	],
})
export class ManagerComponent implements OnInit, OnDestroy {
	constructor(
		private toastrService: NbToastrService,
		private clipboard: ClipboardService,
		private resp: ResponsiveSizeInfoRx,
		public modal: Modal,
		private router: Router,
		private route: ActivatedRoute,
		private sidebarService: NbSidebarService,
		private tasksQueueService: TasksQueueService
	) {}
	homeMode = false;
	fileMode = false;
	mainBar = false;

	@ViewChild(FileModeComponent) file: FileModeComponent;
	@ViewChild(HomeModeComponent) home: HomeModeComponent;
	@ViewChild(RemoteDetailComponent) remoteDetail: RemoteDetailComponent;
	@ViewChild('MobileRemoteDetail') remoteDetailMobile: TemplateRef<any>;
	@ViewChild(FileDetailComponent) fileDetail: FileDetailComponent;
	@ViewChild('MobileFileDetail') fileDetailMobile: TemplateRef<any>;

	private navTrigger = new Subject<NavigationFlowOutNode>();
	nav$: NavigationFlow;

	private mkdirTrigger = new Subject<string>();
	mkdir$: OperationsMkdirFlow;

	clipboardSize = 0;

	private pasteTrigger = new Subject<IManipulate[]>();

	public orderCnt = 0;

	pcDetailViewEnable = false;
	pcDetailView = false;

	visable = false;

	loading() {
		if (this.fileMode) this.file.loading();
		else if (this.homeMode) this.home.loading();
	}
	refresh() {
		if (this.homeMode) this.home.refresh();
		else if (this.fileMode) this.file.refresh();
	}

	addrJump(addr: NavigationFlowOutNode) {
		this.loading();
		this.navTrigger.next(addr);
	}

	private navDeploy() {
		const outer = this;
		this.nav$ = new (class extends NavigationFlow {
			public prerequest$ = outer.navTrigger.pipe(
				distinctUntilChanged((x, y) => JSON.stringify(x) === JSON.stringify(y)),
				map(
					(x): CombErr<NavigationFlowOutNode> => {
						let remote = x.remote;
						if (remote && remote === '') remote = undefined;
						let path = x.path;
						if (path && path === '') path = undefined;

						outer.homeMode = !remote;
						outer.fileMode = !!remote;
						return [{ remote, path }, []];
					}
				)
			);
		})();
		this.nav$.deploy();
		this.navTrigger.next({});
	}

	mkdirDialog() {
		this.modal
			.open(MkdirDialogComponent, overlayConfigFactory({ isBlocking: false }, VEXModalContext))
			.result.then(
				newDir => {
					if (newDir && newDir !== '') this.mkdirTrigger.next(newDir);
				},
				() => {}
			);
	}

	private mkdirDeploy() {
		const outer = this;
		outer.mkdirTrigger.pipe(withLatestFrom(outer.nav$.getOutput())).subscribe(
			([path, navNode]): CombErr<NavigationFlowOutNode> => {
				if (navNode[1].length !== 0) return navNode as any;
				if (navNode[0].path) {
					path = [navNode[0].path, path].join('/');
				}
				outer.toastrService.default('Creating directory', 'Waiting...');
				this.tasksQueueService.AddTaskMkdir([{ remote: navNode[0].remote, path }, []]).then(x => {
					if (x[1].length !== 0) {
						this.toastrService.danger('create dir failure');
					} else {
						this.toastrService.success('create dir success');
					}
				});
			}
		);
	}
	private clipboardDeploy() {
		this.clipboard.clipboard$.getOutput().subscribe(node => {
			if (node[1].length !== 0) return;
			this.clipboardSize = node[0].clipboard.values.length;
		});
	}
	private pasteDeploy() {
		this.pasteTrigger.pipe(withLatestFrom(this.nav$.getOutput())).subscribe(([opers, dstNode]) => {
			if (dstNode[1].length !== 0) throw Error("can't not get destination.");
			opers.forEach(oper => {
				this.clipboard.post(dstNode[0], oper).then(val => {
					if (val[1].length === 0)
						this.toastrService.success(`"${oper}" tasks sent to server`, 'Success', {
							icon: Manipulate2Icon(oper),
						});
					else
						this.toastrService.danger(`"${oper}" tasks sent to server`, 'Failure', {
							icon: Manipulate2Icon(oper),
							destroyByClick: true,
						});
				});
			});
		});
	}

	paste() {
		this.pasteTrigger.next(['copy', 'move']);
	}

	clipboardDialog() {
		this.modal
			.open(ClipboardDialogComponent, overlayConfigFactory({ isBlocking: false }, VEXModalContext))
			.result.then(
				confirm => {
					if (confirm === true) this.pasteTrigger.next(['del']);
				},
				() => {}
			);
	}
	private routeDeploy() {
		this.route.queryParams
			.pipe(
				takeWhile(() => this.visable),
				distinctUntilChanged((x, y) => JSON.stringify(x) === JSON.stringify(y))
			)
			.subscribe(params => {
				this.navTrigger.next(params);
			});
		this.nav$
			.getOutput()
			.pipe(takeWhile(() => this.visable))
			.subscribe(navNode => {
				if (navNode[1].length !== 0) return;
				const params: any = {};
				if (navNode[0].remote && navNode[0].remote !== '') params.remote = navNode[0].remote;
				if (navNode[0].path && navNode[0].path !== '') params.path = navNode[0].path;
				this.router.navigate([], { queryParams: params });
			});
	}

	private sidebarDeploy() {
		this.resp.getResponsiveSize.subscribe(data => {
			this.mainBar = !(data === 'xs' || data === 'sm' || data === 'md');
			this.pcDetailViewEnable = data !== 'xs';
			if (data === 'xs') {
				this.pcDetailView = false;
				this.sidebarService.collapse('detail');
			}
		});
	}

	toggleDetail() {
		this.pcDetailView = !this.pcDetailView;
		this.sidebarService.toggle(false, 'detail');
	}

	openRemoteDetail(item: NavigationFlowOutNode) {
		if (this.pcDetailView) this.remoteDetail.navNode(item);
		if (!this.pcDetailViewEnable) {
			this.modal.open(
				this.remoteDetailMobile,
				overlayConfigFactory({ isBlocking: false, navNode: item }, VEXModalContext)
			);
		}
	}
	openFileDetail(item: OperationsListExtendsFlowOutItemNode) {
		if (this.pcDetailView) this.fileDetail.itemNode(item);
		if (!this.pcDetailViewEnable) {
			this.modal.open(
				this.fileDetailMobile,
				overlayConfigFactory({ isBlocking: false, itemNode: item }, VEXModalContext)
			);
		}
	}

	ngOnInit(): void {
		this.visable = true;
		this.sidebarDeploy();
		this.navDeploy();
		this.routeDeploy();
		this.mkdirDeploy();
		this.clipboardDeploy();
		this.pasteDeploy();
	}

	ngOnDestroy() {
		this.visable = false;
	}
}