package de.ugoe.cs.swe.exercises.exercise;

import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.ide.FileStoreEditorInput;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.core.filesystem.EFS;
import org.eclipse.core.filesystem.IFileStore;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.custom.CCombo;
import de.ugoe.cs.swe.exercises.lecture.Lecture;
import de.ugoe.cs.swe.exercises.lecture.LectureLabelProvider;
import de.ugoe.cs.swe.exercises.misc.CKeyword;
import de.ugoe.cs.swe.exercises.misc.KeywordLabelProvider;
import de.ugoe.cs.swe.exercises.svn.SettingsDialog;

import org.eclipse.swt.custom.SashForm;

public class ViewExercise extends ViewPart {
	private Text searchText;
	private Text complexityText;
	private Text titleText;
	private Text exerciseText;
	private Text solutionText;
	private Text keywordText;
	private Table exercisesTable;
	private Table keywordsTable;
	private ExerciseFilter filter;
	private Exercise selected = null;
	private Table lecturesTable;
	private ArrayList<Lecture> lectures;
	private CCombo lectureCombo;
	private TableViewer lecturesTableViewer, keywordsTableViewer,
			exercisesTableViewer;

	public ViewExercise() {

	}

	@Override
	public void createPartControl(Composite parent) {
		final ProgressMonitorDialog progress = new ProgressMonitorDialog(
				getSite().getShell());
		progress.open();

		parent.setLayout(new GridLayout(4, false));
		Label lblSearch = new Label(parent, SWT.NONE);
		lblSearch.setText("Search:");
		searchText = new Text(parent, SWT.BORDER);

		GridData gridData = new GridData(SWT.FILL, SWT.CENTER, false, false, 1,
				1);
		gridData.widthHint = 311;
		searchText.setLayoutData(gridData);
		new Label(parent, SWT.NONE);
		new Label(parent, SWT.NONE);

		exercisesTableViewer = new TableViewer(parent, SWT.BORDER
				| SWT.FULL_SELECTION);
		exercisesTable = exercisesTableViewer.getTable();
		exercisesTable.setHeaderVisible(true);
		{
			GridData gridData_1 = new GridData(SWT.FILL, SWT.FILL, false, true,
					2, 1);
			gridData_1.minimumWidth = 400;
			gridData_1.widthHint = 400;
			exercisesTable.setLayoutData(gridData_1);
		}

		TableColumn tblclmnTitle = new TableColumn(exercisesTable, SWT.LEFT);
		tblclmnTitle.setWidth(260);
		tblclmnTitle.setText("Title");

		TableColumn tblclmnComplexity = new TableColumn(exercisesTable,
				SWT.NONE);
		tblclmnComplexity.setResizable(false);
		tblclmnComplexity.setWidth(20);
		tblclmnComplexity.setText("Complexity");
		exercisesTableViewer.setContentProvider(new ExerciseContentProvider());
		exercisesTableViewer.setLabelProvider(new ExerciseLabelProvider());
		exercisesTableViewer.setInput(getSite());
		filter = new ExerciseFilter();
		exercisesTableViewer.addFilter(filter);
		exercisesTable.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				TableItem item = (TableItem) e.item;
				selectExercise((Exercise) item.getData());
				keywordText.setText("");
				lectureCombo.deselectAll();
				keywordsTableViewer.refresh();
			}
		});

		searchText.addKeyListener(new KeyAdapter() {
			@Override
			public void keyReleased(KeyEvent e) {
				filter.setSearchText(searchText.getText());
				exercisesTableViewer.refresh();
				selectExercise(selected);
			}
		});

		Composite group = new Composite(parent, SWT.NONE);
		group.setLayout(new GridLayout(2, false));
		gridData = new GridData(SWT.FILL, SWT.FILL, true, false, 2, 2);
		gridData.widthHint = 600;
		gridData.heightHint = 411;
		group.setLayoutData(gridData);

		Composite composite_1 = new Composite(group, SWT.NONE);
		composite_1.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false,
				false, 1, 1));
		composite_1.setLayout(new GridLayout(2, false));
		Label lblTitle = new Label(composite_1, SWT.RIGHT);
		lblTitle.setText("Title:");
		titleText = new Text(composite_1, SWT.BORDER);
		titleText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false,
				1, 1));
		Label lblComplexity = new Label(composite_1, SWT.RIGHT);
		lblComplexity.setText("Complexity:");
		complexityText = new Text(composite_1, SWT.BORDER);
		complexityText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false,
				false, 1, 1));
		new Label(group, SWT.NONE);

		lecturesTableViewer = new TableViewer(group, SWT.BORDER
				| SWT.FULL_SELECTION);
		lecturesTable = lecturesTableViewer.getTable();
		lecturesTable.setHeaderVisible(true);
		{
			GridData gridData_1 = new GridData(SWT.FILL, SWT.FILL, true, true,
					1, 1);
			gridData_1.heightHint = 168;
			lecturesTable.setLayoutData(gridData_1);
		}

		TableColumn tblclmnLectures = new TableColumn(lecturesTable, SWT.NONE);
		tblclmnLectures.setWidth(100);
		tblclmnLectures.setText("Lectures");

		lecturesTableViewer
				.setContentProvider(new ExerciseLecturesContentProvider());
		lecturesTableViewer.setLabelProvider(new LectureLabelProvider());
		lecturesTableViewer.setInput(getSite());

		Button btnDeleteLecture = new Button(group, SWT.NONE);
		btnDeleteLecture.setLayoutData(new GridData(SWT.FILL, SWT.BOTTOM,
				false, false, 1, 1));
		btnDeleteLecture.setText("Remove lecture");

		lectureCombo = new CCombo(group, SWT.BORDER);
		lectureCombo.setEditable(false);
		lectureCombo.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false,
				false, 1, 1));

		Button btnAddLecture = new Button(group, SWT.NONE);
		btnAddLecture.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false,
				false, 1, 1));
		btnAddLecture.setText("Add lecture");

		keywordsTableViewer = new TableViewer(group, SWT.BORDER
				| SWT.FULL_SELECTION | SWT.MULTI);

		keywordsTable = keywordsTableViewer.getTable();
		keywordsTable.setHeaderVisible(true);
		{
			GridData gridData_1 = new GridData(SWT.FILL, SWT.FILL, true, true,
					1, 1);
			gridData_1.heightHint = 121;
			keywordsTable.setLayoutData(gridData_1);
		}

		TableColumn tblclmnKeywords = new TableColumn(keywordsTable, SWT.NONE);
		tblclmnKeywords.setWidth(100);
		tblclmnKeywords.setText("Keywords");
		keywordsTableViewer
				.setContentProvider(new ExerciseKeywordContentProvider());
		keywordsTableViewer.setLabelProvider(new KeywordLabelProvider());
		keywordsTableViewer.setInput(getSite());

		Button btnDeleteKeywords = new Button(group, SWT.NONE);
		btnDeleteKeywords.addSelectionListener(new SelectionAdapter() {
			@SuppressWarnings("unchecked")
			@Override
			public void widgetSelected(SelectionEvent e) {
				StructuredSelection sel = ((StructuredSelection) keywordsTableViewer
						.getSelection());
				if (sel.isEmpty())
					return;
				Iterator<CKeyword> keywordsIterator = sel.iterator();
				while (keywordsIterator.hasNext()) {
					CKeyword keyword = keywordsIterator.next();
					CKeyword.deleteKey(keyword.getKeyId(), CKeyword.EXERCISE);
				}

				keywordsTableViewer.refresh();
			}
		});
		btnDeleteKeywords.setLayoutData(new GridData(SWT.FILL, SWT.BOTTOM,
				false, false, 1, 1));
		btnDeleteKeywords.setText("Delete keyword");

		Composite composite = new Composite(group, SWT.NONE);
		composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false,
				1, 1));
		GridLayout gridLayout = new GridLayout(1, false);
		gridLayout.marginHeight = 0;
		gridLayout.marginWidth = 0;
		composite.setLayout(gridLayout);

		keywordText = new Text(composite, SWT.BORDER);
		keywordText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true,
				false, 1, 1));

		Button btnAddKeyword = new Button(group, SWT.NONE);
		btnAddKeyword.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				if (selected == null || keywordText.getText().length() == 0)
					return;
				CKeyword.insertKey(new CKeyword(keywordText.getText(), selected
						.getId()), CKeyword.EXERCISE);
				keywordText.setText("");
				keywordText.setFocus();
				keywordsTableViewer.refresh();
			}
		});
		btnAddKeyword.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false,
				false, 1, 1));
		btnAddKeyword.setText("Add keyword");

		Label lblAufgabentext = new Label(group, SWT.NONE);
		lblAufgabentext.setText("Exercise:");
		new Label(group, SWT.NONE);

		exerciseText = new Text(group, SWT.BORDER | SWT.WRAP | SWT.READ_ONLY);
		gridData = new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1);
		gridData.heightHint = 156;
		exerciseText.setLayoutData(gridData);

		Label lblMusterlsung = new Label(group, SWT.NONE);
		lblMusterlsung.setText("Solution:");
		new Label(group, SWT.NONE);

		solutionText = new Text(group, SWT.BORDER | SWT.WRAP | SWT.READ_ONLY);
		gridData = new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1);
		gridData.heightHint = 160;
		solutionText.setLayoutData(gridData);

		Button btnEditText = new Button(group, SWT.NONE);
		btnEditText.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false,
				false, 1, 1));
		btnEditText.setText("Edit exercise");
		btnEditText.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				SettingsDialog settings = new SettingsDialog(new Shell());
				PlatformUI.getWorkbench().getActiveWorkbenchWindow()
						.getActivePage().setEditorAreaVisible(true);
				File file = new File(System.getProperty("user.home") + "/"
						+ settings.getWorkingDirectory() + "/exercises/"
						+ String.valueOf(selected.getId()) + "solution.tex");
				if (file != null) {
					IWorkbenchPage page = PlatformUI.getWorkbench()
							.getActiveWorkbenchWindow().getActivePage();
					try {
						IFileStore fileStore = EFS.getStore(file.toURI());
						page.openEditor(new FileStoreEditorInput(fileStore),
								"net.sourceforge.texlipse.TexEditor");
					} catch (CoreException ex) {
						ex.printStackTrace();
					}
				} else if (file != null) {
					String msg = "File is null: " + file.getName();
					MessageDialog.openWarning(null, "Problem", msg);
				}

				file = new File(String.valueOf(System.getProperty("user.home")
						+ "/" + settings.getWorkingDirectory() + "/exercises/"
						+ selected.getId())
						+ ".tex");
				if (file != null) {
					IWorkbenchPage page = PlatformUI.getWorkbench()
							.getActiveWorkbenchWindow().getActivePage();
					try {
						IFileStore fileStore = EFS.getStore(file.toURI());
						page.openEditor(new FileStoreEditorInput(fileStore),
								"net.sourceforge.texlipse.TexEditor");
					} catch (CoreException ex) {
						ex.printStackTrace();
					}
				} else if (file != null) {
					String msg = "File is null: " + file.getName();
					MessageDialog.openWarning(null, "Problem", msg);
				}
			}
		});

		Button btnSave = new Button(group, SWT.NONE);
		btnSave.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {

				if (selected == null)
					return;

				boolean validComplexity = true;
				int complexity = -1;
				try {
					complexity = Integer.parseInt(complexityText.getText());
				} catch (Exception exception) {
				}
				validComplexity = complexity <= 10 && complexity >= 0;

				if (titleText.getText().length() == 0) {
					MessageBox validationMessageBox = new MessageBox(getSite()
							.getShell(), SWT.OK);
					validationMessageBox.setText("Invalid form data");
					validationMessageBox
							.setMessage("Please enter an excercise title.");
					validationMessageBox.open();
					return;
				}
				if (!validComplexity) {
					MessageBox validationMessageBox = new MessageBox(getSite()
							.getShell(), SWT.OK);
					validationMessageBox.setText("Invalid form data");
					validationMessageBox
							.setMessage("Please enter a valid complexity (number between 0 and 10).");
					validationMessageBox.open();
					return;
				}

				PlatformUI.getWorkbench().getActiveWorkbenchWindow()
						.getActivePage().setEditorAreaVisible(false);
				IWorkbenchPage page = PlatformUI.getWorkbench()
						.getActiveWorkbenchWindow().getActivePage();
				page.closeAllEditors(true);

				selected.setTitle(titleText.getText());
				selected.setComplexity(complexity);
				selected.setSolution(selected.getSolution());
				selected.setExerciseText(selected.getExerciseText());

				progress.open();
				selected.save();
				progress.close();
				exercisesTableViewer.refresh();
				lecturesTableViewer.refresh();
				keywordsTableViewer.refresh();

				selectExercise(selected);
			}
		});

		gridData = new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1);
		gridData.widthHint = 93;
		btnSave.setLayoutData(gridData);
		btnSave.setText("Save");
		selectNth(0, exercisesTableViewer, keywordsTableViewer);

		keywordText.addKeyListener(new KeyAdapter() {
			@Override
			public void keyReleased(KeyEvent key) {
				if (key.keyCode == SWT.LF || key.keyCode == SWT.CR) {
					CKeyword.insertKey(new CKeyword(0, keywordText.getText(),
							selected.getId()), CKeyword.EXERCISE);
					keywordText.setText("");
					keywordText.setFocus();
					keywordsTableViewer.refresh();
				}
			}
		});

		btnAddLecture.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				if (selected == null || lectureCombo.getSelectionIndex() < 0)
					return;
				selected.addLecture(lectures.get(lectureCombo
						.getSelectionIndex()));
				lectureCombo.deselectAll();
				lecturesTableViewer.refresh();
			}
		});
		btnDeleteLecture.addSelectionListener(new SelectionAdapter() {
			@SuppressWarnings("unchecked")
			@Override
			public void widgetSelected(SelectionEvent e) {
				StructuredSelection sel = ((StructuredSelection) lecturesTableViewer
						.getSelection());
				if (sel.isEmpty() || selected == null)
					return;
				Iterator<Lecture> lectureIterator = sel.iterator();
				while (lectureIterator.hasNext()) {
					Lecture lecture = lectureIterator.next();
					selected.removeLecture(lecture);
				}

				lecturesTableViewer.refresh();
			}
		});

		SashForm sashForm = new SashForm(parent, SWT.NONE);
		sashForm.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false,
				2, 1));

		Button btnAddExercise = new Button(sashForm, SWT.NONE);
		btnAddExercise.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				Exercise exercise = new Exercise("New exercise", "", "", 5);
				progress.open();
				exercise.save();
				progress.close();
				exercisesTableViewer.refresh();
				selectExercise(exercise);
			}
		});
		btnAddExercise.setText("Add Exercise");

		Button btnDeleteExercise = new Button(sashForm, SWT.CENTER);
		btnDeleteExercise.addSelectionListener(new SelectionAdapter() {
			@SuppressWarnings("unchecked")
			@Override
			public void widgetSelected(SelectionEvent e) {
				int index = indexOfExercise(selected);
				StructuredSelection sel = ((StructuredSelection) exercisesTableViewer
						.getSelection());

				if (!sel.isEmpty()) {

					MessageBox deleteMessageBox = new MessageBox(getSite()
							.getShell(), SWT.YES | SWT.NO);
					deleteMessageBox.setText("Delete");
					deleteMessageBox
							.setMessage("Do you really want to delete this exercise?");

					if (deleteMessageBox.open() == SWT.YES) {
						progress.open();
						for (Iterator<Exercise> iterator = sel.iterator(); iterator
								.hasNext();) {
							Exercise delexercise = iterator.next();
							delexercise.delete();
						}
						progress.close();
					}

				}
				exercisesTableViewer.refresh();
				selectNth(index, exercisesTableViewer, keywordsTableViewer);
			}
		});
		btnDeleteExercise.setText("Delete Exercise");
		sashForm.setWeights(new int[] { 1, 1 });

		progress.close();
	}

	@SuppressWarnings("unchecked")
	public void selectNth(int index, final TableViewer tableViewer_1_1,
			final TableViewer keywordsTableViewer) {
		if (tableViewer_1_1.getTable().getItemCount() > 0) {
			if (index < 0)
				index = 0;
			if (tableViewer_1_1.getTable().getItemCount() <= index)
				index = tableViewer_1_1.getTable().getItemCount() - 1;
			tableViewer_1_1.getTable().select(index);
			StructuredSelection sel = ((StructuredSelection) tableViewer_1_1
					.getSelection());
			Iterator<Exercise> iterator = sel.iterator();
			selectExercise(iterator.next());
		}
	}

	@Override
	public void setFocus() {

	}

	public int indexOfExercise(Exercise exercise) {
		for (int i = 0; i < exercisesTableViewer.getTable().getItemCount(); i++) {
			if (((Exercise) exercisesTableViewer.getElementAt(i)).getId() == exercise
					.getId())
				return i;
		}
		return -1;
	}

	public void selectExercise(Exercise exercise) {

		lectures = Lecture.all();
		lectureCombo.removeAll();
		for (Lecture lecture : lectures) {
			lectureCombo.add(lecture.getName());
		}

		for (int i = 0; i < exercisesTableViewer.getTable().getItemCount(); i++) {
			if (((Exercise) exercisesTableViewer.getElementAt(i)).getId() == exercise
					.getId()) {
				exercisesTableViewer.getTable().select(i);
				selected = exercise;
				titleText.setText(selected.getTitle());
				complexityText
						.setText(String.valueOf(selected.getComplexity()));
				// exerciseText.setText(selected.getExerciseText());
				exerciseText.setText(selected.readFromDisk(false));
				solutionText.setText(selected.readFromDisk(true));
				keywordsTableViewer
						.setContentProvider(new ExerciseKeywordContentProvider(
								selected.getId()));
				lecturesTableViewer
						.setContentProvider(new ExerciseLecturesContentProvider(
								selected));
				return;
			}
		}
	}
}
