/*=============================================================================#
 # Copyright (c) 2008, 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.rj.server;

import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;

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

import org.eclipse.statet.rj.data.RJIO;


/**
 * Server-to-Client list with {@link MainCmdItem}s.
 */
@NonNullByDefault
public final class MainCmdS2CList implements RjsComObject, Externalizable {
	
	
	static final AutoIdMap<ComHandler> gComHandlers= new AutoIdMap<>();
	
	
	private int id;
	
	private boolean isBusy;
	
	private @Nullable MainCmdItem first;
	
	
	public MainCmdS2CList(final MainCmdItem first, final boolean isBusy) {
		this.isBusy= isBusy;
		this.first= first;
	}
	
	/**
	 * Constructor for automatic deserialization
	 */
	public MainCmdS2CList() {
		this.isBusy= false;
		this.first= null;
	}
	
	@Override
	public void writeExternal(final ObjectOutput out) throws IOException {
		out.writeShort(this.id);
		
		out.writeBoolean(this.isBusy);
		
		final RJIO io= RJIO.get(out);
		final int check= io.writeCheck1();
		
		MainCmdItem item= this.first;
		if (item != null) {
			do {
				out.writeByte(item.getCmdType());
				item.writeExternal(io);
			} while ((item= item.next) != null);
		}
		out.writeByte(MainCmdItem.T_NONE);
		
		io.writeCheck2(check);
		io.disconnect(out);
	}
	
	@Override
	public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException {
		this.id= in.readUnsignedShort();
		if (this.id != 0) {
			gComHandlers.get(this.id).processMainCmd(in);
			return;
		}
		
		this.isBusy= in.readBoolean();
		
		final RJIO io= RJIO.get(in);
		try {
			final int check= io.readCheck1();
			
			MainCmdItem item;
			{	// first
				final byte cmdType= in.readByte();
				if (cmdType == MainCmdItem.T_NONE) {
					this.first= null;
					io.readCheck2(check);
					return;
				}
				else {
					this.first= item= readItem(cmdType, io);
				}
			}
			while (true) {
				final byte cmdType= in.readByte();
				if (cmdType == MainCmdItem.T_NONE) {
					io.readCheck2(check);
					return;
				}
				else {
					item= item.next= readItem(cmdType, io);
				}
			}
		}
		finally {
			io.disconnect(in);
		}
	}
	
	private MainCmdItem readItem(final byte cmdType, final RJIO io) throws IOException, ClassNotFoundException {
		switch (cmdType) {
		case MainCmdItem.T_CONSOLE_READ_ITEM:
			return new ConsoleReadCmdItem(io);
		case MainCmdItem.T_CONSOLE_WRITE_ITEM:
			return new ConsoleWriteCmdItem(io);
		case MainCmdItem.T_MESSAGE_ITEM:
			return new ConsoleMessageCmdItem(io);
		case MainCmdItem.T_EXT_CLIENT_ITEM:
			return new ExtClientCmdItem(io);
		case MainCmdItem.T_MAIN_CTRL_ITEM:
			return new MainCtrlCmdItem(io);
		case MainCmdItem.T_DATA_ITEM:
			return new DataCmdItem(io);
		case MainCmdItem.T_GRAPHICS_OP_ITEM:
			return new GraOpCmdItem(io);
		case MainCmdItem.T_DBG_ITEM:
			return new DbgCmdItem(io);
		default:
			throw new ClassNotFoundException("Unknown cmdtype id: " + cmdType);
		}
	}
	
	
	public void clear() {
		MainCmdItem item= this.first;
		while (item != null) {
			final MainCmdItem tmp= item;
			item= item.next;
			tmp.next= null;
		}
		this.first= null;
	}
	
	public boolean isEmpty() {
		return (this.first == null);
	}
	
	public void setId(final int id) {
		this.id= (short) id;
	}
	
	public void setBusy(final boolean isBusy) {
		this.isBusy= isBusy;
	}
	
	public void setObjects(final MainCmdItem first) {
		this.first= first;
	}
	
	
	@Override
	public int getComType() {
		return RjsComObject.T_MAIN_LIST;
	}
	
	public MainCmdItem getItems() {
		return this.first;
	}
	
	public boolean isBusy() {
		return this.isBusy;
	}
	
	
	public boolean testEquals(final MainCmdS2CList other) {
		if (this.isBusy != other.isBusy()) {
			return false;
		}
		
		MainCmdItem thisItem= this.first;
		MainCmdItem otherItem= other.first;
		while (thisItem != null && otherItem != null) {
			if (!thisItem.equals(otherItem)) {
				return false;
			}
			thisItem= thisItem.next;
			otherItem= otherItem.next;
		}
		if (thisItem != null || otherItem != null) {
			return false;
		}
		return true;
	}
	
	@Override
	public String toString() {
		final StringBuilder sb= new StringBuilder(128);
		sb.append("MainCmdS2CList (isBusy=");
		sb.append(this.isBusy);
		sb.append("):");
		if (this.first == null) {
			sb.append("\n<ITEM />");
		}
		else {
			MainCmdItem item= this.first;
			int i= 0;
			while (item != null) {
				sb.append("\n<ITEM i=\"");
				sb.append(i);
				sb.append("\">\n");
				sb.append(item.toString());
				sb.append("\n</ITEM>");
				item= item.next;
				i++;
			}
		}
		return sb.toString();
	}
	
}
