/*******************************************************************************
 * Copyright (c) 2000, 2017 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.ui.examples.readmetool;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.PropertyPage;

/**
 * This page will be added to the property page dialog when the "Properties..."
 * popup menu item is selected for Readme files.
 */
public class ReadmeFilePropertyPage extends PropertyPage {

	/**
	 * Utility method that creates a new composite and sets up its layout data.
	 *
	 * @param parent     the parent of the composite
	 * @param numColumns the number of columns in the new composite
	 * @return the newly-created composite
	 */
	protected Composite createComposite(Composite parent, int numColumns) {
		Composite composite = new Composite(parent, SWT.NULL);
		GridLayout layout = new GridLayout();
		layout.numColumns = numColumns;
		composite.setLayout(layout);
		GridData data = new GridData();
		data.verticalAlignment = GridData.FILL;
		data.horizontalAlignment = GridData.FILL;
		composite.setLayoutData(data);
		return composite;
	}

	@Override
	public Control createContents(Composite parent) {

		// ensure the page has no special buttons
		noDefaultAndApplyButton();
		Composite panel = createComposite(parent, 2);

		PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(), IReadmeConstants.PROPERTY_PAGE_CONTEXT);

		// layout the page

		IResource resource = (IResource) getElement();
		IStatus result = null;
		if (resource.getType() == IResource.FILE) {
			Label label = createLabel(panel, MessageUtil.getString("File_name")); //$NON-NLS-1$
			label = createLabel(panel, resource.getName());
			grabExcessSpace(label);

			//
			createLabel(panel, MessageUtil.getString("Path")); //$NON-NLS-1$
			label = createLabel(panel, resource.getFullPath().setDevice(null).toString());
			grabExcessSpace(label);

			//
			createLabel(panel, MessageUtil.getString("Size")); //$NON-NLS-1$
			IFile file = (IFile) resource;
			try (InputStream contentStream = file.getContents(); Reader in = new InputStreamReader(contentStream)) {

				int chunkSize = contentStream.available();
				StringBuilder buffer = new StringBuilder(chunkSize);
				char[] readBuffer = new char[chunkSize];
				int n = in.read(readBuffer);

				while (n > 0) {
					buffer.append(readBuffer);
					n = in.read(readBuffer);
				}

				contentStream.close();
				label = createLabel(panel, Integer.toString(buffer.length()));
			} catch (CoreException e) {
				result = e.getStatus();
				String message = result.getMessage();
				if (message == null)
					label = createLabel(panel, MessageUtil.getString("<Unknown>")); //$NON-NLS-1$
				else
					label = createLabel(panel, message);
			} catch (IOException e) {
				label = createLabel(panel, MessageUtil.getString("<Unknown>")); //$NON-NLS-1$
			}
			grabExcessSpace(label);
			createLabel(panel, MessageUtil.getString("Number_of_sections")); //$NON-NLS-1$
			// We will get the sections property and simply
			// report number of elements found.
			IAdaptable sections = getSections(resource);
			if (sections instanceof AdaptableList) {
				AdaptableList list = (AdaptableList) sections;
				label = createLabel(panel, String.valueOf(list.size()));
				grabExcessSpace(label);
			}
		}

		//
		Label label = createLabel(panel, MessageUtil.getString("Additional_information")); //$NON-NLS-1$
		grabExcessSpace(label);
		GridData gd = (GridData) label.getLayoutData();
		gd.horizontalSpan = 2;
		return new Canvas(panel, 0);
	}

	/**
	 * Utility method that creates a new label and sets up its layout data.
	 *
	 * @param parent the parent of the label
	 * @param text   the text of the label
	 * @return the newly-created label
	 */
	protected Label createLabel(Composite parent, String text) {
		Label label = new Label(parent, SWT.LEFT);
		label.setText(text);
		GridData data = new GridData();
		data.horizontalAlignment = GridData.FILL;
		label.setLayoutData(data);
		return label;
	}

	/**
	 * Returns the readme sections for this resource, or null if not applicable
	 * (resource is not a readme file).
	 */
	private AdaptableList getSections(IAdaptable adaptable) {
		if (adaptable instanceof IFile)
			return ReadmeModelFactory.getInstance().getSections((IFile) adaptable);
		return null;
	}

	/**
	 * Sets this control to grab any excess horizontal space left in the window.
	 *
	 * @param control the control for which to grab excess space
	 */
	private void grabExcessSpace(Control control) {
		GridData gd = (GridData) control.getLayoutData();
		if (gd != null) {
			gd.grabExcessHorizontalSpace = true;
		}
	}

	/**
	 * (non-Javadoc) Method declared on PreferencePage
	 */
	@Override
	public boolean performOk() {
		// nothing to do - read-only page
		return true;
	}
}
