/*=============================================================================#
 # Copyright (c) 2018, 2021 Stephan Wahlbrink and others.
 # 
 # This program and the accompanying materials are made available under the
 # terms of the Eclipse Public License 2.0 which is available at
 # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
 # which is available at https://www.apache.org/licenses/LICENSE-2.0.
 # 
 # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
 # 
 # Contributors:
 #     Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
 #=============================================================================*/

package org.eclipse.statet.jcommons.status;

import java.util.Objects;

import org.eclipse.statet.jcommons.lang.NonNull;
import org.eclipse.statet.jcommons.lang.NonNullByDefault;
import org.eclipse.statet.jcommons.lang.Nullable;


@NonNullByDefault
public class BasicProgressMonitor implements ProgressMonitor {
	
	
	private static final int ROOT_FLAG= 1 << 31;
	
	private static final int INHERITED_FLAGS= (SUPPRESS_BEGINTASK_NAME | SUPPRESS_ISCANCELED);
	
	
	public static class ProgressData {
		
		protected static final byte MAIN_TASK_NAME= 1 << 1;
		protected static final byte SUB_TASK_NAME= 1 << 2;
		protected static final byte PROGRESS_UNKNOWN= 1 << 3;
		protected static final byte PROGRESS_RATE= 1 << 4;
		protected static final byte CANCELED= 1 << 5;
		protected static final byte BLOCKED= 1 << 6;
		
		
		private String mainTaskName= ""; //$NON-NLS-1$
		private @Nullable String subTaskName;
		
		private boolean progressUnknown;
		/** Progress: from 1 to 0 */
		private double progress= 1;
		
		private volatile boolean isCanceled;
		
		private @Nullable Status blocked;
		
		
		public ProgressData() {
		}
		
		
		public String getMainTaskName() {
			return this.mainTaskName;
		}
		
		protected final void setMainTaskName(final String name) {
			if (!Objects.equals(this.mainTaskName, name)) {
				this.mainTaskName= name;
				this.subTaskName= null;
				
				onDataChanged(MAIN_TASK_NAME);
			}
			else if (this.subTaskName != null) {
				this.subTaskName= null;
				
				onDataChanged(SUB_TASK_NAME);
			}
		}
		
		public @Nullable String getSubTaskName() {
			return this.subTaskName;
		}
		
		private final void setSubTaskName(@Nullable String name) {
			if (name != null && name.isEmpty()) {
				name= null;
			}
			if (!Objects.equals(this.subTaskName, name)) {
				this.subTaskName= name;
				
				onDataChanged(SUB_TASK_NAME);
			}
		}
		
		public boolean isProgressUnknown() {
			return this.progressUnknown;
		}
		
		private void setProgressUnknown(final boolean enabled) {
			if (this.progressUnknown != enabled) {
				this.progressUnknown= enabled;
				
				onDataChanged(PROGRESS_UNKNOWN);
			}
		}
		
		public double getProgress() {
			return this.progress;
		}
		
		private void setProgress(final double progress) {
			if (progress < this.progress) {
				this.progress= progress;
				
				onDataChanged(PROGRESS_RATE);
			}
		}
		
		public boolean isCanceled() {
			return this.isCanceled;
		}
		
		protected void setCanceled(final boolean state) {
			if (this.isCanceled != state) {
				this.isCanceled= state;
				
				onDataChanged(CANCELED);
			}
		}
		
		public @Nullable Status getBlocked() {
			return this.blocked;
		}
		
		protected void setBlocked(final Status reason) {
			if (!Objects.equals(this.blocked, reason)) {
				this.blocked= reason;
				
				onDataChanged(BLOCKED);
			}
		}
		
		protected void clearBlocked() {
			if (this.blocked != null) {
				this.blocked= null;
				
				onDataChanged(BLOCKED);
			}
		}
		
		
		protected void onDataChanged(final byte data) {
		}
		
	}
	
	
	protected final ProgressData data;
	
	private final int flags;
	
	private String taskName;
	
	/** Bound (this.workRemaining == 0) for data.progress */
	private final double progressDataDone;
	/** Current work remaining: from x to 0 */
	private int workRemaining;
	/** Current factor: work -> progress */
	private double workProgressFactor;
	
	private @Nullable BasicProgressMonitor currentSub;
	
	
	private BasicProgressMonitor(final ProgressData data, final double progressDone,
			final int flags) {
		this.data= data;
		this.flags= flags;
		this.taskName= data.mainTaskName;
		
		this.progressDataDone= progressDone;
	}
	
	public BasicProgressMonitor(final ProgressData data, final int flags) {
		this(data, 0, ROOT_FLAG | flags);
	}
	
	public BasicProgressMonitor(final ProgressData data) {
		this(data, 0, ROOT_FLAG);
	}
	
	
	@Override
	public void beginTask(final String name, final int totalWork) {
		if ((this.flags & SUPPRESS_BEGINTASK_NAME) == 0 && name != null) {
			this.taskName= name;
			this.data.setMainTaskName(name);
		}
		
		setWorkRemaining(totalWork);
	}
	
	@Override
	public void beginSubTask(final @Nullable String name) {
		checkProgress();
		
		this.data.setSubTaskName(name);
	}
	
	@Override
	public ProgressMonitor setWorkRemaining(final int work) {
		checkProgress();
		
		if (work >= 0) {
			if ((this.flags & ROOT_FLAG) != 0) {
				this.data.setProgressUnknown(false);
			}
			final double progressRemaining= (this.data.progress - this.progressDataDone);
			if (work == 0 || progressRemaining <= 0) {
				this.workProgressFactor= 0;
				
				this.workRemaining= 0;
				this.data.setProgress(this.progressDataDone);
			}
			else {
				this.workRemaining= work;
				this.workProgressFactor= progressRemaining / work;
			}
		}
		else {
			if (work == UNKNOWN) {
				if ((this.flags & ROOT_FLAG) != 0) {
					this.data.setProgressUnknown(true);
				}
			}
			this.workProgressFactor= 0;
		}
		
		return this;
	}
	
	@Override
	public void addWorked(final int work) {
		checkProgress();
		
		this.data.setProgress(consumeWork(work));
	}
	
	@Override
	public @NonNull ProgressMonitor newSubMonitor(final int work, final int flags) {
		checkProgress();
		
		return this.currentSub= new BasicProgressMonitor(this.data, consumeWork(work),
				(this.flags & INHERITED_FLAGS) | flags );
	}
	
	private double consumeWork(final int work) {
		if (work > 0 && this.workProgressFactor != 0) {
			this.workRemaining= Math.max(this.workRemaining - work, 0);
		}
		return this.progressDataDone + this.workRemaining * this.workProgressFactor;
	}
	
	private void checkProgress() {
		final BasicProgressMonitor currentSub= this.currentSub;
		if (currentSub != null) {
			this.currentSub= null;
			this.data.setMainTaskName(this.taskName);
			this.data.setProgress(currentSub.progressDataDone);
		}
	}
	
	
	@Override
	public boolean isCanceled() {
		if ((this.flags & SUPPRESS_ISCANCELED) == 0) {
			return this.data.isCanceled();
		}
		return false;
	}
	
	@Override
	public void setCanceled(final boolean state) {
		this.data.setCanceled(state);
	}
	
	
	@Override
	public void setBlocked(final Status reason) {
		this.data.setBlocked(reason);
	}
	
	@Override
	public void clearBlocked() {
		this.data.clearBlocked();
	}
	
}
