/*=============================================================================#
 # 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;


/**
 * Client-to-Server list with {@link MainCmdItem}s.
 */
@NonNullByDefault
public final class MainCmdC2SList implements RjsComObject, Externalizable {
	
	
	private final @Nullable RJIO privateIO;
	
	private @Nullable MainCmdItem first;
	
	
	public MainCmdC2SList(final RJIO io) {
		this.privateIO= io;
	}
	
	/**
	 * Constructor for automatic deserialization
	 */
	public MainCmdC2SList() {
		this.privateIO= null;
		this.first= null;
	}
	
	@Override
	public void writeExternal(final ObjectOutput out) throws IOException {
		final RJIO io;
		if (this.privateIO != null) {
			io= this.privateIO;
			io.connect(out);
		}
		else {
			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 {
		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_GRAPH_ITEM:
			return new GDCmdItem.Answer(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() {
		this.first= null;
	}
	
	public void setObjects(final MainCmdItem first) {
		this.first= first;
	}
	
	
	@Override
	public int getComType() {
		return RjsComObject.T_MAIN_LIST;
	}
	
	public @Nullable MainCmdItem getItems() {
		return this.first;
	}
	
	public boolean testEquals(final MainCmdC2SList other) {
		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(100);
		sb.append("MainCmdC2SList (");
		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();
	}
	
}
