/*
 * 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.
 */

'use strict';

import * as Util from "util";
import {ComplexObjectType, CompositeType, ObjectType} from "./ObjectType";
import BinaryUtils from "./internal/BinaryUtils";
import BinaryType, {BinaryField, BinaryTypeBuilder} from "./internal/BinaryType";
import ArgumentChecker from "./internal/ArgumentChecker";
import MessageBuffer from "./internal/MessageBuffer";
import Logger from "./internal/Logger";
import { IgniteClientError } from "./Errors";
import { PRIMITIVE_TYPE } from "./internal/Constants";
import BinaryCommunicator from "./internal/BinaryCommunicator";

const HEADER_LENGTH = 24;
const VERSION = 1;

// user type
const FLAG_USER_TYPE = 0x0001;
// schema exists
const FLAG_HAS_SCHEMA = 0x0002;
// object contains raw data
const FLAG_HAS_RAW_DATA = 0x0004;
// offsets take 1 byte
const FLAG_OFFSET_ONE_BYTE = 0x0008;
// offsets take 2 bytes
const FLAG_OFFSET_TWO_BYTES = 0x0010;
// compact footer, no field IDs
const FLAG_COMPACT_FOOTER = 0x0020;

/**
 * Class representing a complex Ignite object in the binary form.
 *
 * It corresponds to COMPOSITE_TYPE.COMPLEX_OBJECT {@link ObjectType.COMPOSITE_TYPE},
 * has mandatory type Id, which corresponds to a name of the complex type,
 * and includes optional fields.
 *
 * An instance of the BinaryObject can be obtained/created by the following ways:
 *   - returned by the client when a complex object is received from Ignite cache
 * and is not deserialized to another JavaScript object.
 *   - created using the public constructor. Fields may be added to such an instance using setField() method.
 *   - created from a JavaScript object using static fromObject() method.
 */
export class BinaryObject {
    private _typeBuilder: BinaryTypeBuilder;
    private _modified: boolean;
    private _hasSchema: boolean;
    private _compactFooter: boolean;
    private _hasRawData: boolean;
    private _fields: Map<number, BinaryObjectField>;
    private _buffer: MessageBuffer;
    private _startPos: number;
    private _hashCode: number;
    private _schemaOffset: number;
    private _length: number;
    private _offsetType: PRIMITIVE_TYPE;

    /**
     * Creates an instance of the BinaryObject without any fields.
     *
     * Fields may be added later using setField() method.
     *
     * @param {string} typeName - name of the complex type to generate the type Id.
     *
     * @return {BinaryObject} - new BinaryObject instance.
     *
     * @throws {IgniteClientError} if error.
     */
    constructor(typeName: string) {
        ArgumentChecker.notEmpty(typeName, 'typeName');
        this._buffer = null;
        this._fields = new Map<number, BinaryObjectField>();
        this._typeBuilder = BinaryTypeBuilder.fromTypeName(typeName);
        this._modified = false;
        this._schemaOffset = null;
        this._hasSchema = false;
        this._compactFooter = false;
        this._hasRawData = false;
        this._hashCode = null;
    }

    /**
     * Creates an instance of the BinaryObject from the specified instance of JavaScript Object.
     *
     * All fields of the JavaScript Object instance with their values are added to the BinaryObject.
     * Fields may be added or removed later using setField() and removeField() methods.
     *
     * If complexObjectType parameter is specified, then the type Id is taken from it.
     * Otherwise, the type Id is generated from the name of the JavaScript Object.
     *
     * @async
     *
     * @param {object} jsObject - instance of JavaScript Object
     *   which adds and initializes the fields of the BinaryObject instance.
     * @param {ComplexObjectType} [complexObjectType] - instance of complex type definition
     *   which specifies non-standard mapping of the fields of the BinaryObject instance
     *   to/from the Ignite types.
     *
     * @return {BinaryObject} - new BinaryObject instance.
     *
     * @throws {IgniteClientError} if error.
     */
    static async fromObject(jsObject, complexObjectType = null) {
        ArgumentChecker.notEmpty(jsObject, 'jsObject');
        ArgumentChecker.hasType(complexObjectType, 'complexObjectType', false, ComplexObjectType);
        const typeBuilder = BinaryTypeBuilder.fromObject(jsObject, complexObjectType);
        const result = new BinaryObject(typeBuilder.getTypeName());
        result._typeBuilder = typeBuilder;
        let fieldName;
        for (let field of result._typeBuilder.getFields()) {
            fieldName = field.name;
            if (jsObject && jsObject[fieldName] !== undefined) {
                result.setField(
                    fieldName,
                    jsObject[fieldName],
                    complexObjectType ? complexObjectType._getFieldType(fieldName) : null);
            }
            else {
                throw IgniteClientError.serializationError(
                    true, Util.format('field "%s" is undefined', fieldName));
            }
        }
        return result;
    }

    /**
     * Sets the new value of the specified field.
     * Adds the specified field, if it did not exist before.
     *
     * Optionally, specifies a type of the field.
     * If the type is not specified then during operations the Ignite client
     * will try to make automatic mapping between JavaScript types and Ignite object types -
     * according to the mapping table defined in the description of the {@link ObjectType} class.
     *
     * @param {string} fieldName - name of the field.
     * @param {*} fieldValue - new value of the field.
     * @param {ObjectType.PRIMITIVE_TYPE | CompositeType} [fieldType] - type of the field:
     *   - either a type code of primitive (simple) type
     *   - or an instance of class representing non-primitive (composite) type
     *   - or null (or not specified) that means the type is not specified.
     *
     * @return {BinaryObject} - the same instance of BinaryObject
     *
     * @throws {IgniteClientError} if error.
     */
    setField(fieldName, fieldValue, fieldType = null) {
        ArgumentChecker.notEmpty(fieldName, 'fieldName');
        this._modified = true;
        const field = new BinaryObjectField(fieldName, fieldValue, fieldType);
        this._fields.set(field.id, field);
        this._typeBuilder.setField(fieldName, field.typeCode);
        return this;
    }

    /**
     * Removes the specified field.
     * Does nothing if the field does not exist.
     *
     * @param {string} fieldName - name of the field.
     *
     * @return {BinaryObject} - the same instance of BinaryObject
     *
     * @throws {IgniteClientError} if error.
     */
    removeField(fieldName) {
        ArgumentChecker.notEmpty(fieldName, 'fieldName');
        this._modified = true;
        this._fields.delete(BinaryField._calculateId(fieldName));
        this._typeBuilder.removeField(fieldName);
        return this;
    }

    /**
     * Checks if the specified field exists in this BinaryObject instance.
     *
     * @param {string} fieldName - name of the field.
     *
     * @return {boolean} - true if exists, false otherwise.
     *
     * @throws {IgniteClientError} if error.
     */
    hasField(fieldName) {
        ArgumentChecker.notEmpty(fieldName, 'fieldName');
        return this._fields.has(BinaryField._calculateId(fieldName));
    }

    /**
     * Returns a value of the specified field.
     *
     * Optionally, specifies a type of the field.
     * If the type is not specified then the Ignite client
     * will try to make automatic mapping between JavaScript types and Ignite object types -
     * according to the mapping table defined in the description of the {@link ObjectType} class.
     *
     * @async
     *
     * @param {string} fieldName - name of the field.
     * @param {ObjectType.PRIMITIVE_TYPE | CompositeType} [fieldType] - type of the field:
     *   - either a type code of primitive (simple) type
     *   - or an instance of class representing non-primitive (composite) type
     *   - or null (or not specified) that means the type is not specified.
     *
     * @return {*} - value of the field or JavaScript undefined if the field does not exist.
     *
     * @throws {IgniteClientError} if error.
     */
    async getField(fieldName, fieldType = null) {
        ArgumentChecker.notEmpty(fieldName, 'fieldName');
        const field = this._fields.get(BinaryField._calculateId(fieldName));
        return field ? await field.getValue(fieldType) : undefined;
    }

    /**
     * Deserializes this BinaryObject instance into an instance of the specified complex object type.
     *
     * @async
     *
     * @param {ComplexObjectType} complexObjectType - instance of class representing complex object type.
     *
     * @return {object} - instance of the JavaScript object
     *   which corresponds to the specified complex object type.
     *
     * @throws {IgniteClientError} if error.
     */
    async toObject(complexObjectType) {
        ArgumentChecker.notNull(complexObjectType, 'complexObjectType');
        ArgumentChecker.hasType(complexObjectType, 'complexObjectType', false, ComplexObjectType);
        const result = new (complexObjectType._objectConstructor);
        let binaryField;
        let fieldName;
        for (let field of this._fields.values()) {
            binaryField = this._typeBuilder.getField(field.id);
            if (!binaryField) {
                throw IgniteClientError.serializationError(
                    false, Util.format('field with id "%s" can not be deserialized', field.id));
            }
            fieldName = binaryField.name;
            result[fieldName] = await field.getValue(complexObjectType._getFieldType(fieldName));
        }
        return result;
    }

    /**
     * Returns type name of this BinaryObject instance.
     *
     * @return {string} - type name.
     */
    getTypeName() {
        return this._typeBuilder.getTypeName();
    }

    get fields() {
        return this._fields;
    }

    /**
     * Returns names of all fields of this BinaryObject instance.
     *
     * @return {Array<string>} - names of all fields.
     *
     * @throws {IgniteClientError} if error.
     */
    getFieldNames() {
        return this._typeBuilder.schema.fieldIds.map(fieldId => {
            const field = this._typeBuilder.getField(fieldId);
            if (field) {
                return field.name;
            }
            else {
                throw IgniteClientError.internalError(
                    Util.format('Field "%s" is absent in binary type fields', fieldId));
            }
        });
    }

    /** Private methods */

    /**
     * @ignore
     */
    static _isFlagSet(flags, flag) {
        return (flags & flag) === flag;
    }

    /**
     * @ignore
     */
    static async _fromBuffer(communicator: BinaryCommunicator, buffer: MessageBuffer) {
        const result = new BinaryObject(new ComplexObjectType({}).typeName);
        result._buffer = buffer;
        result._startPos = buffer.position;
        await result._read(communicator);
        return result;
    }

    /**
     * @ignore
     */
    async _getHashCode(communicator: BinaryCommunicator) {
        if (this._hashCode !== null && !this._modified) {
            return this._hashCode;
        }

        await this._write(communicator, new MessageBuffer());
        return this._hashCode;
    }

    /**
     * @ignore
     */
    _getTypeId() {
        return this._typeBuilder.getTypeId();
    }

    /**
     * @ignore
     */
    async _write(communicator, buffer) {
        if (this._buffer && !this._modified) {
            buffer.writeBuffer(this._buffer.buffer, this._startPos, this._startPos + this._length);
        }
        else {
            await this._typeBuilder.finalize(communicator);
            this._startPos = buffer.position;
            buffer.position = this._startPos + HEADER_LENGTH;
            this._hasSchema = (this._fields.size > 0);
            if (this._hasSchema) {
                let field;
                // write fields
                for (field of this._fields.values()) {
                    await field._writeValue(communicator, buffer, this._typeBuilder.getField(field.id).typeCode);
                }
                this._schemaOffset = buffer.position - this._startPos;
                this._offsetType = field.getOffsetType(this._startPos);
                // write schema
                for (let field of this._fields.values()) {
                    field._writeOffset(buffer, this._startPos, this._offsetType);
                }
            }
            else {
                this._schemaOffset = 0;
            }
            this._length = buffer.position - this._startPos;
            this._buffer = buffer;
            // write header
            this._writeHeader();
            this._buffer.position = this._startPos + this._length;
            this._modified = false;
        }

        if (Logger.debug) {
            Logger.logDebug('BinaryObject._write [' + [...this._buffer.getSlice(this._startPos, this._startPos + this._length)] + ']');
        }
    }

    /**
     * @ignore
     */
    _writeHeader() {
        this._buffer.position = this._startPos;
        // type code
        this._buffer.writeByte(BinaryUtils.TYPE_CODE.COMPLEX_OBJECT);
        // version
        this._buffer.writeByte(VERSION);
        // flags
        let flags = FLAG_USER_TYPE;
        if (this._hasSchema) {
            flags = flags | FLAG_HAS_SCHEMA | FLAG_COMPACT_FOOTER;
        }
        if (this._offsetType === BinaryUtils.TYPE_CODE.BYTE) {
            flags = flags | FLAG_OFFSET_ONE_BYTE;
        }
        else if (this._offsetType === BinaryUtils.TYPE_CODE.SHORT) {
            flags = flags | FLAG_OFFSET_TWO_BYTES;
        }
        this._buffer.writeShort(flags);
        // type id
        this._buffer.writeInteger(this._typeBuilder.getTypeId());
        // hash code
        this._hashCode = BinaryUtils.contentHashCode(
            this._buffer, this._startPos + HEADER_LENGTH, this._schemaOffset - 1);
        this._buffer.writeInteger(this._hashCode);
        // length
        this._buffer.writeInteger(this._length);
        // schema id
        this._buffer.writeInteger(this._hasSchema ? this._typeBuilder.getSchemaId() : 0);
        // schema offset
        this._buffer.writeInteger(this._schemaOffset);
    }

    /**
     * @ignore
     */
    async _read(communicator) {
        await this._readHeader(communicator);
        if (this._hasSchema) {
            this._buffer.position = this._startPos + this._schemaOffset;
            const fieldOffsets = [];
            const fieldIds = this._typeBuilder.schema.fieldIds;
            let index = 0;
            let fieldId;
            let schemaEndOffset = this._startPos + this._length;
            if (this._hasRawData) {
                schemaEndOffset -= BinaryUtils.getSize(BinaryUtils.TYPE_CODE.INTEGER);
            }
            while (this._buffer.position < schemaEndOffset) {
                if (!this._compactFooter) {
                    fieldId = this._buffer.readInteger();
                    this._typeBuilder.schema.addField(fieldId);
                }
                else {
                    if (index >= fieldIds.length) {
                        throw IgniteClientError.serializationError(
                            false, 'wrong number of fields in schema');
                    }
                    fieldId = fieldIds[index];
                    index++;
                }
                fieldOffsets.push([fieldId, this._buffer.readNumber(this._offsetType, false)]);
            }
            fieldOffsets.sort((val1, val2) => val1[1] - val2[1]);
            let offset;
            let nextOffset;
            let field;
            for (let i = 0; i < fieldOffsets.length; i++) {
                fieldId = fieldOffsets[i][0];
                offset = fieldOffsets[i][1];
                nextOffset = i + 1 < fieldOffsets.length ? fieldOffsets[i + 1][1] : this._schemaOffset;
                field = BinaryObjectField._fromBuffer(
                    communicator,this._buffer, this._startPos + offset, nextOffset - offset, fieldId);
                this._fields.set(field.id, field);
            }
        }
        this._buffer.position = this._startPos + this._length;
    }

    /**
     * @ignore
     */
    async _readHeader(communicator) {
        // type code
        this._buffer.readByte();
        // version
        const version = this._buffer.readByte();
        if (version !== VERSION) {
            throw IgniteClientError.internalError();
        }
        // flags
        const flags = this._buffer.readShort();
        // type id
        const typeId = this._buffer.readInteger();
        // hash code
        this._hashCode = this._buffer.readInteger();
        // length
        this._length = this._buffer.readInteger();
        // schema id
        const schemaId = this._buffer.readInteger();
        // schema offset
        this._schemaOffset = this._buffer.readInteger();
        this._hasSchema = BinaryObject._isFlagSet(flags, FLAG_HAS_SCHEMA);
        this._compactFooter = BinaryObject._isFlagSet(flags, FLAG_COMPACT_FOOTER);
        this._hasRawData = BinaryObject._isFlagSet(flags, FLAG_HAS_RAW_DATA);
        this._offsetType = BinaryObject._isFlagSet(flags, FLAG_OFFSET_ONE_BYTE) ?
            BinaryUtils.TYPE_CODE.BYTE :
            BinaryObject._isFlagSet(flags, FLAG_OFFSET_TWO_BYTES) ?
                BinaryUtils.TYPE_CODE.SHORT :
                BinaryUtils.TYPE_CODE.INTEGER;
        this._typeBuilder = await BinaryTypeBuilder.fromTypeId(communicator, typeId, this._compactFooter ? schemaId : null);
    }
}

/**
 * @ignore
 */
export class BinaryObjectField {

    private _name: string;

    private _id: number;

    private _value: object;

    private _type: PRIMITIVE_TYPE | CompositeType;

    private _typeCode: number;

    private _communicator: BinaryCommunicator;

    private _buffer: MessageBuffer;

    private _offset: number;

    private _length: number;

    constructor(name: string, value = undefined, type = null) {
        this._name = name;
        this._id = BinaryField._calculateId(name);
        this._value = value;
        this._type = type;
        if (!type && value !== undefined && value !== null) {
            this._type = BinaryUtils.calcObjectType(value);
        }
        this._typeCode = null;
        if (this._type) {
            this._typeCode = BinaryUtils.getTypeCode(this._type);
        }
    }

    get id() {
        return this._id;
    }

    get typeCode() {
        return this._typeCode;
    }

    async getValue(type = null) {
        if (this._value === undefined || this._buffer && this._type !== type) {
            this._buffer.position = this._offset;
            this._value = await this._communicator.readObject(this._buffer, type);
            this._type = type;
        }
        return this._value;
    }

    getOffsetType(headerStartPos) {
        let offset = this._offset - headerStartPos;
        if (offset < 0x100) {
            return BinaryUtils.TYPE_CODE.BYTE;
        }
        else if (offset < 0x10000) {
            return BinaryUtils.TYPE_CODE.SHORT;
        }
        return BinaryUtils.TYPE_CODE.INTEGER;
    }

    static _fromBuffer(communicator: BinaryCommunicator, buffer: MessageBuffer, offset: number, length: number, id: number) {
        const result = new BinaryObjectField(null);
        result._id = id;
        result._communicator = communicator;
        result._buffer = buffer;
        result._offset = offset;
        result._length = length;
        return result;
    }

    async _writeValue(communicator, buffer, expectedTypeCode) {
        const offset = buffer.position;
        if (this._buffer && this._communicator === communicator) {
            buffer.writeBuffer(this._buffer.buffer, this._offset, this._offset + this._length);
        }
        else {
            if (this._value === undefined) {
                await this.getValue();
            }
            BinaryUtils.checkCompatibility(this._value, expectedTypeCode);
            await communicator.writeObject(buffer, this._value, this._type);
        }
        this._communicator = communicator;
        this._buffer = buffer;
        this._length = buffer.position - offset;
        this._offset = offset;
    }

    _writeOffset(buffer, headerStartPos, offsetType) {
        buffer.writeNumber(this._offset - headerStartPos, offsetType, false);
    }
}
