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

import org.eclipse.statet.rj.data.RJIO;
import org.eclipse.statet.rj.data.RJIOExternalizable;
import org.eclipse.statet.rj.server.gr.Coord;
import org.eclipse.statet.rj.server.gr.GraOp;


/**
 * Command item for main loop graphic operations (="op")
 */
public final class GraOpCmdItem extends MainCmdItem implements GraOp {
	
	
	private static final int OV_WITHDATA=                  0x01000000;
	private static final int OV_WITHSTATUS=                0x08000000;
	
	
	private final int devId;
	private final byte op;
	
	private RJIOExternalizable data;
	
	
	/**
	 * Constructor for new commands
	 */
	public GraOpCmdItem(final int devId, final byte op) {
		this.devId= devId;
		this.op= op;
	}
	
	/**
	 * Constructor for new commands
	 */
	public GraOpCmdItem(final int devId, final byte op, final RJIOExternalizable data) {
		this.devId= devId;
		this.op= op;
		if (data != null) {
			this.data= data;
			this.options |= OV_WITHDATA;
		}
	}
	
	/**
	 * Constructor for deserialization
	 */
	public GraOpCmdItem(final RJIO in) throws IOException {
		this.requestId= in.readInt();
		this.options= in.readInt();
		this.devId= in.readInt();
		this.op= in.readByte();
		if ((this.options & OV_WITHSTATUS) != 0) {
			this.data= new RjsStatus(in);
		}
		else if ((this.options & OV_WITHDATA) != 0) {
			switch (this.op) {
			case OP_CONVERT_DEV2USER:
			case OP_CONVERT_USER2DEV:
				this.data= new Coord(in);
				break;
			default:
				break;
			}
		}
	}
	
	@Override
	public void writeExternal(final RJIO out) throws IOException {
		out.writeInt(this.requestId);
		out.writeInt(this.options);
		out.writeInt(this.devId);
		out.writeByte(this.op);
		if ((this.options & (OV_WITHSTATUS | OV_WITHDATA)) != 0) {
			this.data.writeExternal(out);
		}
	}
	
	
	@Override
	public byte getCmdType() {
		return T_GRAPHICS_OP_ITEM;
	}
	
	
	@Override
	public void setAnswer(final RjsStatus status) {
		assert (status != null);
		if (status.getSeverity() == RjsStatus.OK) {
			this.options= (this.options & OM_CLEARFORANSWER) | OV_ANSWER;
			this.data= null;
		}
		else {
			this.options= (this.options & OM_CLEARFORANSWER) | (OV_ANSWER | OV_WITHSTATUS);
			this.data= status;
		}
	}
	
	public void setAnswer(final RJIOExternalizable data) {
		this.options= (this.options & OM_CLEARFORANSWER) | OV_ANSWER;
		if (data != null) {
			this.options |= OV_WITHDATA;
		}
		this.data= data;
	}
	
	
	public int getDevId() {
		return this.devId;
	}
	
	@Override
	public byte getOp() {
		return this.op;
	}
	
	@Override
	public boolean isOK() {
		return ((this.options & OV_WITHSTATUS) == 0 || this.data == null);
	}
	
	@Override
	public RjsStatus getStatus() {
		if ((this.options & OV_ANSWER) != 0) {
			return ((this.options & OV_WITHSTATUS) == 0) ? RjsStatus.OK_STATUS : (RjsStatus) this.data;
		}
		return null;
	}
	
	@Override
	public String getDataText() {
		return null;
	}
	
	public Object getData() {
		return this.data;
	}
	
	
	@Override
	public boolean testEquals(final MainCmdItem other) {
		if (!(other instanceof GraOpCmdItem)) {
			return false;
		}
		final GraOpCmdItem otherItem= (GraOpCmdItem) other;
		if (this.devId != otherItem.devId) {
			return false;
		}
		if (this.op != otherItem.op) {
			return false;
		}
		if (this.options != otherItem.options) {
			return false;
		}
		return true;
	}
	
	@Override
	public String toString() {
		final StringBuilder sb= new StringBuilder(128);
		sb.append("GDOpCmdItem ");
		switch (this.op) {
		case OP_CLOSE:
			sb.append("CLOSE");
			break;
		default:
			sb.append(this.op);
			break;
		}
		sb.append("\n\t").append("options= 0x").append(Integer.toHexString(this.options));
		if ((this.options & OV_WITHSTATUS) != 0) {
			sb.append("\nwith status: ");
			sb.append((this.data == null) ? RjsStatus.OK_STATUS : this.data);
		}
		else if ((this.options & OV_WITHDATA) != 0) {
			sb.append("\n<DATA>\n");
			sb.append(this.data);
			sb.append("\n</DATA>");
		}
		else {
			sb.append("\n<DATA/>");
		}
		return sb.toString();
	}
	
}
