import Tensor from './tensor'
import {OpAttrs,OpData,OpNode} from './interface/interface'

/**
 * @file   Kernel.ts
 * @brief  Class Kernel is defined to express the order of execution of the kernel in the network 
 *         structure and resource management.
 * @author Siyu Xu(xusiyu@sensetime.com).
 *
 * @copyright Copyright (c) 2014-2021 SenseTime Group Limited.
 */

export default  abstract class Kernel {
    protected name_: string = '';
    protected type_: string = '';
    public data_: OpData = {} as OpData;
    protected param_:OpAttrs = {} as OpAttrs;

    //we should record the in/out Tensor infomation in model
    protected inTensors_: Tensor[] = [] as Tensor[];
    protected outTensors_: Tensor[] = [] as Tensor[];
    protected tmpTensor_: Tensor = null as unknown as Tensor;; //record the temp data
    //tensor is shared by other op,so we need record the real input/output shape
    protected inShape_:number[][] = [] as number[][];
    protected outShape_:number[][] = [] as number[][];
    //TODO
    constructor(opNode:OpNode) {
        this.name_ = opNode.props.name;
        this.type_ = opNode.props.type;
        this.param_ = opNode.attrs;
        this.data_ = opNode.data;
    }
    abstract releaseKernelResource():number ;
    abstract initKernelParam():number;
    
    /* forward function is extends for subclass to implement*/
    abstract  forward():number; 
    abstract  tempBufferSize():number; 

    public setTmpTensor(data:Tensor):number {this.tmpTensor_ = data; return 0;}
    //abstract  forward(): Promise<boolean>;
    public set name(name: string){ this.name_ = name;}
    public set kernelType(kernelType: string){ this.type_ = kernelType; }
    
    public get name(){ return this.name_;}
    public get kernelType(){ return this.type_;}

    public addInTensor(t: Tensor): number{ this.inTensors_.push(t);return 0;}
    public addInShape(t: number[]): number{ this.inShape_.push(t);return 0;}

    public addOutTensor(t: Tensor): number{ this.outTensors_.push(t); return 0;}
    public addOutShape(t: number[]): number{ this.outShape_.push(t);return 0;}

    public getInTensorCount(): number{ return this.inTensors_.length;}
    public getOutTensorCount(): number{ return this.outTensors_.length;}

    public getInTensor(index:number): Tensor{ return this.inTensors_[index];}
    public getInShape(index:number): number[]{ return this.inShape_[index];}

    public getOutTensor(index:number): Tensor{return this.outTensors_[index];}
    public getOutShape(index:number): number[]{ return this.outShape_[index];}

};