import { Location } from "../../memory/location";
import { IType } from "../../typeSystem/itype";
import { IStoreValue } from "./value/istore_value";

export class StoreObject {

  private _type: IType;
  private _loc_address: number;
  private _readOnly: boolean;
  private _id?: String;

  /**
   * 
   * @param {Type} type 
   * @param {Number} loc_address 
   * @param {Boolean} readOnly 
   */
  constructor (type: IType, loc_address: number, readOnly = false) {
    this._loc_address = loc_address;
    this._type = type;
    this._readOnly = readOnly;
    this._id = undefined;
  }

  setID (id: String) {
    this._id = id;
  }

  get id () {
    return this._id;
  }

  get inStore () {
    return this.id !== null;
  }

  get type () {
    return this._type;
  }

  /**
   * Returns the actual value stored at the loccation address present in this object.
   * The returned value is compatible with @prop{StoreObject.type}
  */
  get value () {
    const address = Location.find(this._loc_address);
    if (address != null) {
      return address.value
    } else {
      throw new Error("!!!Critical Error: variable "+this.id+" does not have a valid address. Loc-Address "+ this.locAddress);
    }
  }
  
  get number () {
    throw new Error("DOT NOT USE THIS PROPERTY!");
  }

  get readOnly () {
    return this._readOnly;
  }

  set readOnly (value) {
    this._readOnly = value;
  }

  isCompatible (another: IStoreValue) {
    return this.type.isCompatible(another.type);
  }

  destroy () {
    return Location.deallocate(this._loc_address);
  }

  get locAddress () {
    return this._loc_address;
  }
}
