/*
 * Copyright (c) 2016 Manumitting Technologies Inc. and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Manumitting Technologies Inc - initial API and implementation
 */
package org.eclipse.userstorage.sdk.browser;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.action.StatusLineContributionItem;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.layout.TableColumnLayout;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.CellLabelProvider;
import org.eclipse.jface.viewers.ColumnWeightData;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.layout.RowData;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.userstorage.IBlob;
import org.eclipse.userstorage.IStorage;
import org.eclipse.userstorage.StorageFactory;
import org.eclipse.userstorage.internal.util.StringUtil;
import org.eclipse.userstorage.oauth.EclipseOAuthCredentialsProvider;
import org.eclipse.userstorage.oauth.OAuthParameters;

public class USSBrowsingView extends ViewPart {
	private static final String APP_TOKEN_OOMPH = "cNhDr0INs8T109P8h6E1r_GvU3I";
	private static final String APP_TOKEN_MPC = "MZ04RMOpksKN5GpxKXafq2MSjSP";

	private TableViewer viewer;
	private Action showMPCBucketAction;
	private Action showOomphBucketAction;
	private Action setOAuthParametersAction;
	private Action restoreDefaultOAuthParametersAction;;

	private StatusLineContributionItem statusText;
	private Text appTokenText;
	private Button useOAuth;

	private EditableOAuthParameters oauthParameters;

	private OAuthClientDetailsDialog dialog;

	public USSBrowsingView() {
	}

	private void resetDefaults() {
		oauthParameters = new EditableOAuthParameters();
		dialog = new OAuthClientDetailsDialog(getSite().getShell(), oauthParameters);
		refresh();
	}

	public void createPartControl(Composite c) {
		resetDefaults();
		Composite parent = new Composite(c, SWT.NONE);

		{
			Composite header = new Composite(parent, SWT.NONE);
			header.setLayout(new RowLayout());
			Label label = new Label(header, SWT.NONE);
			label.setText("Application Token:");
			appTokenText = new Text(header, SWT.SINGLE | SWT.BORDER);
			appTokenText.setMessage("Application token");
			GC gc = new GC(appTokenText);
			int fontWidth = gc.getFontMetrics().getAverageCharWidth();
			gc.dispose();
			appTokenText.setLayoutData(new RowData(30 * fontWidth, SWT.DEFAULT));
			useOAuth = new Button(header, SWT.CHECK);
			useOAuth.setText("Use OAuth?");
			useOAuth.setSelection(true);

			appTokenText.addSelectionListener(new SelectionAdapter() {
				@Override
				public void widgetDefaultSelected(SelectionEvent e) {
					refresh();
				}
			});
			useOAuth.addSelectionListener(new SelectionAdapter() {
				@Override
				public void widgetDefaultSelected(SelectionEvent e) {
					refresh();
				}
			});
		}

		Composite tableContainer = new Composite(parent, SWT.NONE);
		TableColumnLayout tableLayout = new TableColumnLayout();
		tableContainer.setLayout(tableLayout);
		viewer = new TableViewer(tableContainer, SWT.BORDER | SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
		viewer.getTable().setHeaderVisible(true);
		viewer.setContentProvider(ArrayContentProvider.getInstance());
		GridDataFactory.defaultsFor(viewer.getControl()).grab(true, true).applyTo(viewer.getControl());

		TableViewerColumn tvcBlobId = new TableViewerColumn(viewer, SWT.LEFT);
		tableLayout.setColumnData(tvcBlobId.getColumn(), new ColumnWeightData(20));
		tvcBlobId.getColumn().setText("Blob ID");
		tvcBlobId.setLabelProvider(new CellLabelProvider() {
			@Override
			public void update(ViewerCell cell) {
				IBlob blob = (IBlob) cell.getElement();
				cell.setText(blob.getKey());
			}
		});

		TableViewerColumn tvcBlobContent = new TableViewerColumn(viewer, SWT.LEFT);
		tableLayout.setColumnData(tvcBlobContent.getColumn(), new ColumnWeightData(80));
		tvcBlobContent.getColumn().setText("Content");
		tvcBlobContent.setLabelProvider(new CellLabelProvider() {
			@Override
			public void update(ViewerCell cell) {
				// FIXME: do this in the background
				try {
					IBlob blob = (IBlob) cell.getElement();
					String text = blob.getContentsUTF();
					cell.setText(text);
				} catch (IllegalStateException e) {
					e.printStackTrace();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		});

		GridDataFactory.fillDefaults().grab(true, true).applyTo(tableContainer);
		GridLayoutFactory.fillDefaults().generateLayout(parent);

		getSite().setSelectionProvider(viewer);
		makeActions();
		hookContextMenu();
		hookDoubleClickAction();
		contributeToActionBars();

	}

	private void refresh() {
		if (appTokenText == null) {
			// not yet rendered
			return;
		}
		applicationTokenChanged(appTokenText.getText(), useOAuth.getSelection());
	}

	protected void applicationTokenChanged(String appToken, boolean useOAuth) {
		getViewSite().getActionBars().getStatusLineManager().setErrorMessage(null);
		try {
			final IStorage storage = StorageFactory.DEFAULT.create(appToken);
			if (useOAuth) {
				EclipseOAuthCredentialsProvider credentialsProvider = new EclipseOAuthCredentialsProvider(oauthParameters);
				credentialsProvider.setShell(getViewSite());
				storage.setCredentialsProvider(credentialsProvider);
			}
			Job loadBlobs = new Job("Load blobs") {
				@Override
				protected IStatus run(IProgressMonitor monitor) {
					SubMonitor progress = SubMonitor.convert(monitor);
					final List<IBlob> blobs = new ArrayList<IBlob>();
					try {
						for (IBlob b : storage.getBlobs()) {
							blobs.add(b);
							progress.worked(1);
						}
					} catch (IOException e) {
						return new Status(IStatus.ERROR, getClass().getName(), 0, "Unable to load blobs", e);
					}
					asyncExec(new Runnable() {
						public void run() {
							update(storage, blobs);
							done(Status.OK_STATUS);
						}
					});
					return ASYNC_FINISH;
				}
			};
			loadBlobs.schedule();
		} catch (Exception e) {
			getViewSite().getActionBars().getStatusLineManager().setErrorMessage(e.getMessage());
		}
	}

	protected void update(IStorage storage, List<IBlob> blobs) {
		viewer.setInput(blobs);
		statusText.setText("Service: " + storage.getService().toString());
		statusText.getParent().update(true);
	}

	protected void asyncExec(Runnable runnable) {
		Display d = getSite().getShell().getDisplay();
		if (!d.isDisposed()) {
			d.asyncExec(runnable);
		}
	}

	private void hookContextMenu() {
		MenuManager menuMgr = new MenuManager("#PopupMenu");
		menuMgr.setRemoveAllWhenShown(true);
		menuMgr.addMenuListener(new IMenuListener() {
			public void menuAboutToShow(IMenuManager manager) {
				fillContextMenu(manager);
			}
		});
		Menu menu = menuMgr.createContextMenu(viewer.getControl());
		viewer.getControl().setMenu(menu);
		getSite().registerContextMenu(menuMgr, viewer);
	}

	private void contributeToActionBars() {
		IActionBars bars = getViewSite().getActionBars();
		fillLocalPullDown(bars.getMenuManager());
		fillLocalToolBar(bars.getToolBarManager());

		statusText = new StatusLineContributionItem(getViewSite().getId());
		bars.getStatusLineManager().add(statusText);
	}

	private void fillLocalPullDown(IMenuManager manager) {
		manager.add(showMPCBucketAction);
		manager.add(showOomphBucketAction);
		manager.add(new Separator());
		manager.add(setOAuthParametersAction);
		manager.add(restoreDefaultOAuthParametersAction);
	}

	private void fillContextMenu(IMenuManager manager) {
		// Other plug-ins can contribute there actions here
		manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
	}

	private void fillLocalToolBar(IToolBarManager manager) {
	}

	private void makeActions() {
		showMPCBucketAction = new Action() {
			public void run() {
				appTokenText.setText(APP_TOKEN_MPC);
				useOAuth.setSelection(true);
				applicationTokenChanged(APP_TOKEN_MPC, true);
			}
		};
		showMPCBucketAction.setText("Browse Marketplace Data");
		showMPCBucketAction.setToolTipText("Use Eclipse Marketplace USS application token");

		showOomphBucketAction = new Action() {
			public void run() {
				appTokenText.setText(APP_TOKEN_OOMPH);
				useOAuth.setSelection(true);
				applicationTokenChanged(APP_TOKEN_OOMPH, true);
			}
		};
		showOomphBucketAction.setText("Browse Oomph Data");
		showOomphBucketAction.setToolTipText("Use Oomph USS application token");

		restoreDefaultOAuthParametersAction = new Action() {
			public void run() {
				resetDefaults();
			}
		};
		restoreDefaultOAuthParametersAction.setText("Restore Default OAuth Client Parameters");

		setOAuthParametersAction = new Action() {
			public void run() {
				if (dialog.open() == OAuthClientDetailsDialog.OK) {
					refresh();
				}
			}
		};
		setOAuthParametersAction.setText("Set OAuth Client Parameters");

		// doubleClickAction = new Action() {
		// public void run() {
		// ISelection selection = viewer.getSelection();
		// Object obj = ((IStructuredSelection) selection).getFirstElement();
		// showMessage("Double-click detected on " + obj.toString());
		// }
		// };
	}

	private void hookDoubleClickAction() {
		// viewer.addDoubleClickListener(new IDoubleClickListener() {
		// public void doubleClick(DoubleClickEvent event) {
		// doubleClickAction.run();
		// }
		// });
	}

	public void setFocus() {
		viewer.getControl().setFocus();
	}
}
