/*
 * 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.compress.colgroup.dictionary;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.io.Serializable;

import org.apache.sysds.runtime.compress.colgroup.indexes.IColIndex;
import org.apache.sysds.runtime.data.SparseBlock;
import org.apache.sysds.runtime.functionobjects.Builtin;
import org.apache.sysds.runtime.functionobjects.ValueFunction;
import org.apache.sysds.runtime.instructions.cp.CM_COV_Object;
import org.apache.sysds.runtime.matrix.data.MatrixBlock;
import org.apache.sysds.runtime.matrix.operators.BinaryOperator;
import org.apache.sysds.runtime.matrix.operators.ScalarOperator;
import org.apache.sysds.runtime.matrix.operators.UnaryOperator;

public class PlaceHolderDict implements IDictionary, Serializable {

    private static final long serialVersionUID = 9176356558592L;

    private static final String errMessage = "PlaceHolderDict does not support Operations, and is purely intended for serialization";

    /** The number of values supposed to be contained in this dictionary */
    private final int nVal;

    public PlaceHolderDict(int nVal) {
        this.nVal = nVal;
    }

    @Override
    public double[] getValues() {
        throw new RuntimeException(errMessage);
    }

    @Override
    public double getValue(int i) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public double getValue(int r, int col, int nCol) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public long getInMemorySize() {
        return 16 + 4;
    }

    @Override
    public double aggregate(double init, Builtin fn) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public double aggregateWithReference(double init, Builtin fn, double[] reference, boolean def) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public double[] aggregateRows(Builtin fn, int nCol) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public double[] aggregateRowsWithDefault(Builtin fn, double[] defaultTuple) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public double[] aggregateRowsWithReference(Builtin fn, double[] reference) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public void aggregateCols(double[] c, Builtin fn, IColIndex colIndexes) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public void aggregateColsWithReference(double[] c, Builtin fn, IColIndex colIndexes, double[] reference,
        boolean def) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public IDictionary applyScalarOp(ScalarOperator op) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public IDictionary applyScalarOpAndAppend(ScalarOperator op, double v0, int nCol) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public IDictionary applyUnaryOp(UnaryOperator op) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public IDictionary applyUnaryOpAndAppend(UnaryOperator op, double v0, int nCol) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public IDictionary applyScalarOpWithReference(ScalarOperator op, double[] reference, double[] newReference) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public IDictionary applyUnaryOpWithReference(UnaryOperator op, double[] reference, double[] newReference) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public IDictionary binOpLeft(BinaryOperator op, double[] v, IColIndex colIndexes) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public IDictionary binOpLeftAndAppend(BinaryOperator op, double[] v, IColIndex colIndexes) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public IDictionary binOpLeftWithReference(BinaryOperator op, double[] v, IColIndex colIndexes, double[] reference,
        double[] newReference) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public IDictionary binOpRight(BinaryOperator op, double[] v, IColIndex colIndexes) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public IDictionary binOpRightAndAppend(BinaryOperator op, double[] v, IColIndex colIndexes) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public IDictionary binOpRight(BinaryOperator op, double[] v) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public IDictionary binOpRightWithReference(BinaryOperator op, double[] v, IColIndex colIndexes, double[] reference,
        double[] newReference) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public void write(DataOutput out) throws IOException {
        out.writeByte(DictionaryFactory.Type.PLACE_HOLDER.ordinal());
        out.writeInt(nVal);
    }

    public static PlaceHolderDict read(DataInput in) throws IOException {
        int nVals = in.readInt();
        return new PlaceHolderDict(nVals);
    }

    @Override
    public long getExactSizeOnDisk() {
        return 1 + 4;
    }

    @Override
    public DictType getDictType() {
        throw new RuntimeException(errMessage);
    }

    @Override
    public int getNumberOfValues(int ncol) {
        return nVal;
    }

    @Override
    public double[] sumAllRowsToDouble(int nrColumns) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public double[] sumAllRowsToDoubleWithDefault(double[] defaultTuple) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public double[] sumAllRowsToDoubleWithReference(double[] reference) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public double[] sumAllRowsToDoubleSq(int nrColumns) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public double[] sumAllRowsToDoubleSqWithDefault(double[] defaultTuple) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public double[] sumAllRowsToDoubleSqWithReference(double[] reference) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public double[] productAllRowsToDouble(int nrColumns) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public double[] productAllRowsToDoubleWithDefault(double[] defaultTuple) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public double[] productAllRowsToDoubleWithReference(double[] reference) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public void colSum(double[] c, int[] counts, IColIndex colIndexes) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public void colSumSq(double[] c, int[] counts, IColIndex colIndexes) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public void colSumSqWithReference(double[] c, int[] counts, IColIndex colIndexes, double[] reference) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public double sum(int[] counts, int nCol) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public double sumSq(int[] counts, int nCol) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public double sumSqWithReference(int[] counts, double[] reference) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public String getString(int colIndexes) {
        return ""; // get string empty
    }

    @Override
    public IDictionary sliceOutColumnRange(int idxStart, int idxEnd, int previousNumberOfColumns) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public boolean containsValue(double pattern) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public boolean containsValueWithReference(double pattern, double[] reference) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public long getNumberNonZeros(int[] counts, int nCol) {
        return -1;
    }

    @Override
    public long getNumberNonZerosWithReference(int[] counts, double[] reference, int nRows) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public void addToEntry(double[] v, int fr, int to, int nCol) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public void addToEntry(double[] v, int fr, int to, int nCol, int rep) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public void addToEntryVectorized(double[] v, int f1, int f2, int f3, int f4, int f5, int f6, int f7, int f8, int t1,
        int t2, int t3, int t4, int t5, int t6, int t7, int t8, int nCol) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public IDictionary subtractTuple(double[] tuple) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public MatrixBlockDictionary getMBDict(int nCol) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public IDictionary scaleTuples(int[] scaling, int nCol) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public IDictionary preaggValuesFromDense(int numVals, IColIndex colIndexes, IColIndex aggregateColumns, double[] b,
        int cut) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public IDictionary replace(double pattern, double replace, int nCol) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public IDictionary replaceWithReference(double pattern, double replace, double[] reference) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public void product(double[] ret, int[] counts, int nCol) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public void productWithDefault(double[] ret, int[] counts, double[] def, int defCount) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public void productWithReference(double[] ret, int[] counts, double[] reference, int refCount) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public void colProduct(double[] res, int[] counts, IColIndex colIndexes) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public void colProductWithReference(double[] res, int[] counts, IColIndex colIndexes, double[] reference) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public CM_COV_Object centralMoment(ValueFunction fn, int[] counts, int nRows) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public CM_COV_Object centralMoment(CM_COV_Object ret, ValueFunction fn, int[] counts, int nRows) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public CM_COV_Object centralMomentWithDefault(ValueFunction fn, int[] counts, double def, int nRows) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public CM_COV_Object centralMomentWithDefault(CM_COV_Object ret, ValueFunction fn, int[] counts, double def,
        int nRows) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public CM_COV_Object centralMomentWithReference(ValueFunction fn, int[] counts, double reference, int nRows) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public CM_COV_Object centralMomentWithReference(CM_COV_Object ret, ValueFunction fn, int[] counts, double reference,
        int nRows) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public IDictionary rexpandCols(int max, boolean ignore, boolean cast, int nCol) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public IDictionary rexpandColsWithReference(int max, boolean ignore, boolean cast, int reference) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public double getSparsity() {
        throw new RuntimeException(errMessage);
    }

    @Override
    public void multiplyScalar(double v, double[] ret, int off, int dictIdx, IColIndex cols) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public void TSMMWithScaling(int[] counts, IColIndex rows, IColIndex cols, MatrixBlock ret) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public void MMDict(IDictionary right, IColIndex rowsLeft, IColIndex colsRight, MatrixBlock result) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public void MMDictDense(double[] left, IColIndex rowsLeft, IColIndex colsRight, MatrixBlock result) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public void MMDictSparse(SparseBlock left, IColIndex rowsLeft, IColIndex colsRight, MatrixBlock result) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public void TSMMToUpperTriangle(IDictionary right, IColIndex rowsLeft, IColIndex colsRight, MatrixBlock result) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public void TSMMToUpperTriangleDense(double[] left, IColIndex rowsLeft, IColIndex colsRight, MatrixBlock result) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public void TSMMToUpperTriangleSparse(SparseBlock left, IColIndex rowsLeft, IColIndex colsRight,
        MatrixBlock result) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public void TSMMToUpperTriangleScaling(IDictionary right, IColIndex rowsLeft, IColIndex colsRight, int[] scale,
        MatrixBlock result) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public void TSMMToUpperTriangleDenseScaling(double[] left, IColIndex rowsLeft, IColIndex colsRight, int[] scale,
        MatrixBlock result) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public void TSMMToUpperTriangleSparseScaling(SparseBlock left, IColIndex rowsLeft, IColIndex colsRight, int[] scale,
        MatrixBlock result) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public IDictionary cbind(IDictionary that, int nCol) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public boolean equals(IDictionary o) {
        return o instanceof PlaceHolderDict;
    }

    @Override
    public IDictionary reorder(int[] reorder) {
        throw new RuntimeException(errMessage);
    }

    @Override
    public IDictionary clone() {
        return new PlaceHolderDict(nVal);
    }

}
