/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.apache.sysds.runtime.instructions.fed;

import org.apache.sysds.runtime.DMLRuntimeException;
import org.apache.sysds.runtime.controlprogram.caching.MatrixObject;
import org.apache.sysds.runtime.controlprogram.context.ExecutionContext;
import org.apache.sysds.runtime.controlprogram.federated.FederatedRequest;
import org.apache.sysds.runtime.controlprogram.federated.FederationUtils;
import org.apache.sysds.runtime.functionobjects.OffsetColumnIndex;
import org.apache.sysds.runtime.instructions.InstructionUtils;
import org.apache.sysds.runtime.instructions.cp.CPOperand;
import org.apache.sysds.runtime.matrix.operators.Operator;
import org.apache.sysds.runtime.matrix.operators.ReorgOperator;
import org.apache.sysds.runtime.meta.DataCharacteristics;

public class AppendFEDInstruction extends BinaryFEDInstruction {
	protected boolean _cbind; //otherwise rbind
	
	protected AppendFEDInstruction(Operator op, CPOperand in1, CPOperand in2, CPOperand out,
		boolean cbind, String opcode, String istr) {
		super(FEDType.Append, op, in1, in2, out, opcode, istr);
		_cbind = cbind;
	}
	
	public static AppendFEDInstruction parseInstruction(String str) {
		String[] parts = InstructionUtils.getInstructionPartsWithValueType(str);
		InstructionUtils.checkNumFields(parts, 5, 4);
		
		String opcode = parts[0];
		CPOperand in1 = new CPOperand(parts[1]);
		CPOperand in2 = new CPOperand(parts[2]);
		CPOperand out = new CPOperand(parts[parts.length - 2]);
		boolean cbind = Boolean.parseBoolean(parts[parts.length - 1]);
		
		Operator op = new ReorgOperator(OffsetColumnIndex.getOffsetColumnIndexFnObject(-1));
		return new AppendFEDInstruction(op, in1, in2, out, cbind, opcode, str);
	}
	
	@Override
	public void processInstruction(ExecutionContext ec) {
		//get inputs
		MatrixObject mo1 = ec.getMatrixObject(input1.getName());
		MatrixObject mo2 = ec.getMatrixObject(input2.getName());
		DataCharacteristics dc1 = mo1.getDataCharacteristics();
		DataCharacteristics dc2 = mo1.getDataCharacteristics();
		
		//check input dimensions
		if (_cbind && mo1.getNumRows() != mo2.getNumRows()) {
			throw new DMLRuntimeException(
				"Append-cbind is not possible for federated input matrices " + input1.getName() + " and "
				+ input2.getName() + " with different number of rows: " + mo1.getNumRows() + " vs "
				+ mo2.getNumRows());
		}
		else if (!_cbind && mo1.getNumColumns() != mo2.getNumColumns()) {
			throw new DMLRuntimeException(
				"Append-rbind is not possible for federated input matrices " + input1.getName() + " and "
				+ input2.getName() + " with different number of columns: " + mo1.getNumColumns()
				+ " vs " + mo2.getNumColumns());
		}
		
		if( mo1.isFederated() && _cbind ) {
			FederatedRequest fr1 = mo1.getFedMapping().broadcast(mo2);
			FederatedRequest fr2 = FederationUtils.callInstruction(instString, output,
				new CPOperand[]{input1, input2}, new long[]{mo1.getFedMapping().getID(), fr1.getID()});
			mo1.getFedMapping().execute(fr1, fr2);
			//derive new fed mapping for output
			MatrixObject out = ec.getMatrixObject(output);
			out.getDataCharacteristics().set(dc1.getRows(), dc1.getCols()+dc2.getCols(),
				dc1.getBlocksize(), dc1.getNonZeros()+dc2.getNonZeros());
			out.setFedMapping(mo1.getFedMapping().copyWithNewID(fr2.getID()));
		}
		else if( mo1.isFederated() && mo2.isFederated() && !_cbind ) {
			MatrixObject out = ec.getMatrixObject(output);
			out.getDataCharacteristics().set(dc1.getRows()+dc2.getRows(), dc1.getCols(),
				dc1.getBlocksize(), dc1.getNonZeros()+dc2.getNonZeros());
			long id = FederationUtils.getNextFedDataID();
			out.setFedMapping(mo1.getFedMapping().copyWithNewID(id).rbind(dc1.getRows(), mo2.getFedMapping()));
		}
		else { //other combinations
			throw new DMLRuntimeException("Federated AggregateBinary not supported with the "
				+ "following federated objects: "+mo1.isFederated()+" "+mo2.isFederated());
		}
	}
}
