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

/**
 * @author Jorge Bay Gondra
 */
'use strict';

const t = require('../../process/traversal');
const ts = require('../../process/traversal-strategy');
const Bytecode = require('../../process/bytecode');
const g = require('../graph');
const utils = require('../../utils');

const valueKey = '@value';
const typeKey = '@type';

/**
 * @abstract
 */
class TypeSerializer {
  serialize() {
    throw new Error('serialize() method not implemented for ' + this.constructor.name);
  }

  deserialize() {
    throw new Error('deserialize() method not implemented for ' + this.constructor.name);
  }

  canBeUsedFor() {
    throw new Error('canBeUsedFor() method not implemented for ' + this.constructor.name);
  }
}

class NumberSerializer extends TypeSerializer {
  serialize(item) {
    if (isNaN(item)) {
      return {
        [typeKey]: 'g:Double',
        [valueKey]: 'NaN',
      };
    } else if (item === Number.POSITIVE_INFINITY) {
      return {
        [typeKey]: 'g:Double',
        [valueKey]: 'Infinity',
      };
    } else if (item === Number.NEGATIVE_INFINITY) {
      return {
        [typeKey]: 'g:Double',
        [valueKey]: '-Infinity',
      };
    }
    return item;
  }

  deserialize(obj) {
    const val = obj[valueKey];
    if (val === 'NaN') {
      return NaN;
    } else if (val === 'Infinity') {
      return Number.POSITIVE_INFINITY;
    } else if (val === '-Infinity') {
      return Number.NEGATIVE_INFINITY;
    }
    return parseFloat(val);
  }

  canBeUsedFor(value) {
    return typeof value === 'number';
  }
}

class DateSerializer extends TypeSerializer {
  serialize(item) {
    return {
      [typeKey]: 'g:Date',
      [valueKey]: item.getTime(),
    };
  }

  deserialize(obj) {
    return new Date(obj[valueKey]);
  }

  canBeUsedFor(value) {
    return value instanceof Date;
  }
}

class LongSerializer extends TypeSerializer {
  serialize(item) {
    return {
      [typeKey]: 'g:Int64',
      [valueKey]: item.value,
    };
  }

  canBeUsedFor(value) {
    return value instanceof utils.Long;
  }
}

class BytecodeSerializer extends TypeSerializer {
  serialize(item) {
    let bytecode = item;
    if (item instanceof t.Traversal) {
      bytecode = item.getBytecode();
    }
    const result = {};
    result[typeKey] = 'g:Bytecode';
    const resultValue = (result[valueKey] = {});
    const sources = this._serializeInstructions(bytecode.sourceInstructions);
    if (sources) {
      resultValue['source'] = sources;
    }
    const steps = this._serializeInstructions(bytecode.stepInstructions);
    if (steps) {
      resultValue['step'] = steps;
    }
    return result;
  }

  _serializeInstructions(instructions) {
    if (instructions.length === 0) {
      return null;
    }
    const result = new Array(instructions.length);
    result[0] = instructions[0];
    for (let i = 0; i < instructions.length; i++) {
      result[i] = instructions[i].map((item) => this.writer.adaptObject(item));
    }
    return result;
  }

  canBeUsedFor(value) {
    return value instanceof Bytecode || value instanceof t.Traversal;
  }
}

class PSerializer extends TypeSerializer {
  /** @param {P} item */
  serialize(item) {
    const result = {};
    result[typeKey] = 'g:P';
    const resultValue = (result[valueKey] = {
      predicate: item.operator,
    });
    if (item.other === undefined || item.other === null) {
      resultValue['value'] = this.writer.adaptObject(item.value);
    } else {
      resultValue['value'] = [this.writer.adaptObject(item.value), this.writer.adaptObject(item.other)];
    }
    return result;
  }

  canBeUsedFor(value) {
    return value instanceof t.P;
  }
}

class TextPSerializer extends TypeSerializer {
  /** @param {TextP} item */
  serialize(item) {
    const result = {};
    result[typeKey] = 'g:TextP';
    const resultValue = (result[valueKey] = {
      predicate: item.operator,
    });
    if (item.other === undefined || item.other === null) {
      resultValue['value'] = this.writer.adaptObject(item.value);
    } else {
      resultValue['value'] = [this.writer.adaptObject(item.value), this.writer.adaptObject(item.other)];
    }
    return result;
  }

  canBeUsedFor(value) {
    return value instanceof t.TextP;
  }
}

class LambdaSerializer extends TypeSerializer {
  /** @param {Function} item */
  serialize(item) {
    const lambdaDef = item();

    // check if the language is specified otherwise assume gremlin-groovy.
    const returnIsString = typeof lambdaDef === 'string';
    const script = returnIsString ? lambdaDef : lambdaDef[0];
    const lang = returnIsString ? 'gremlin-groovy' : lambdaDef[1];

    // detect argument count
    const argCount =
      lang === 'gremlin-groovy' && script.includes('->')
        ? script.substring(0, script.indexOf('->')).includes(',')
          ? 2
          : 1
        : -1;

    return {
      [typeKey]: 'g:Lambda',
      [valueKey]: {
        arguments: argCount,
        language: lang,
        script: script,
      },
    };
  }

  canBeUsedFor(value) {
    return typeof value === 'function';
  }
}

class EnumSerializer extends TypeSerializer {
  /** @param {EnumValue} item */
  serialize(item) {
    return {
      [typeKey]: 'g:' + item.typeName,
      [valueKey]: item.elementName,
    };
  }

  canBeUsedFor(value) {
    return value && value.typeName && value instanceof t.EnumValue;
  }
}

class TraverserSerializer extends TypeSerializer {
  /** @param {Traverser} item */
  serialize(item) {
    return {
      [typeKey]: 'g:Traverser',
      [valueKey]: {
        value: this.writer.adaptObject(item.object),
        bulk: this.writer.adaptObject(item.bulk),
      },
    };
  }

  deserialize(obj) {
    const value = obj[valueKey];
    return new t.Traverser(this.reader.read(value['value']), this.reader.read(value['bulk']));
  }

  canBeUsedFor(value) {
    return value instanceof t.Traverser;
  }
}

class TraversalStrategySerializer extends TypeSerializer {
  /** @param {TraversalStrategy} item */
  serialize(item) {
    const conf = {};
    for (const k in item.configuration) {
      if (item.configuration.hasOwnProperty(k)) {
        conf[k] = this.writer.adaptObject(item.configuration[k]);
      }
    }

    return {
      [typeKey]: 'g:' + item.constructor.name,
      [valueKey]: conf,
    };
  }

  canBeUsedFor(value) {
    return value instanceof ts.TraversalStrategy;
  }
}

class VertexSerializer extends TypeSerializer {
  deserialize(obj) {
    const value = obj[valueKey];
    return new g.Vertex(this.reader.read(value['id']), value['label'], this.reader.read(value['properties']));
  }

  /** @param {Vertex} item */
  serialize(item) {
    return {
      [typeKey]: 'g:Vertex',
      [valueKey]: {
        id: this.writer.adaptObject(item.id),
        label: item.label,
      },
    };
  }

  canBeUsedFor(value) {
    return value instanceof g.Vertex;
  }
}

class VertexPropertySerializer extends TypeSerializer {
  deserialize(obj) {
    const value = obj[valueKey];
    return new g.VertexProperty(
      this.reader.read(value['id']),
      value['label'],
      this.reader.read(value['value']),
      this.reader.read(value['properties']),
    );
  }
}

class PropertySerializer extends TypeSerializer {
  deserialize(obj) {
    const value = obj[valueKey];
    return new g.Property(value['key'], this.reader.read(value['value']));
  }
}

class EdgeSerializer extends TypeSerializer {
  deserialize(obj) {
    const value = obj[valueKey];
    return new g.Edge(
      this.reader.read(value['id']),
      new g.Vertex(this.reader.read(value['outV']), this.reader.read(value['outVLabel'])),
      value['label'],
      new g.Vertex(this.reader.read(value['inV']), this.reader.read(value['inVLabel'])),
      this.reader.read(value['properties']),
    );
  }

  /** @param {Edge} item */
  serialize(item) {
    return {
      [typeKey]: 'g:Edge',
      [valueKey]: {
        id: this.writer.adaptObject(item.id),
        label: item.label,
        outV: this.writer.adaptObject(item.outV.id),
        outVLabel: item.outV.label,
        inV: this.writer.adaptObject(item.inV.id),
        inVLabel: item.inV.label,
      },
    };
  }

  canBeUsedFor(value) {
    return value instanceof g.Edge;
  }
}

class PathSerializer extends TypeSerializer {
  deserialize(obj) {
    const value = obj[valueKey];
    const objects = value['objects'].map((o) => this.reader.read(o));
    return new g.Path(this.reader.read(value['labels']), objects);
  }
}

class Path3Serializer extends TypeSerializer {
  deserialize(obj) {
    const value = obj[valueKey];
    return new g.Path(this.reader.read(value['labels']), this.reader.read(value['objects']));
  }
}

class TSerializer extends TypeSerializer {
  deserialize(obj) {
    return t.t[obj[valueKey]];
  }
}

class DirectionSerializer extends TypeSerializer {
  deserialize(obj) {
    return t.direction[obj[valueKey].toLowerCase()];
  }
}

class ArraySerializer extends TypeSerializer {
  constructor(typeKey) {
    super();
    this.typeKey = typeKey;
  }

  deserialize(obj) {
    const value = obj[valueKey];
    if (!Array.isArray(value)) {
      throw new Error('Expected Array, obtained: ' + value);
    }
    return value.map((x) => this.reader.read(x));
  }

  /** @param {Array} item */
  serialize(item) {
    return {
      [typeKey]: this.typeKey,
      [valueKey]: item.map((x) => this.writer.adaptObject(x)),
    };
  }

  canBeUsedFor(value) {
    return Array.isArray(value);
  }
}

class BulkSetSerializer extends TypeSerializer {
  deserialize(obj) {
    const value = obj[valueKey];
    if (!Array.isArray(value)) {
      throw new Error('Expected Array, obtained: ' + value);
    }

    // coerce the BulkSet to List. if the bulk exceeds the int space then we can't coerce to List anyway,
    // so this query will be trouble. we'd need a legit BulkSet implementation here in js. this current
    // implementation is here to replicate the previous functionality that existed on the server side in
    // previous versions.
    let result = [];
    for (let ix = 0, iy = value.length; ix < iy; ix += 2) {
      const pair = value.slice(ix, ix + 2);
      result = result.concat(Array(this.reader.read(pair[1])).fill(this.reader.read(pair[0])));
    }

    return result;
  }
}

class MapSerializer extends TypeSerializer {
  deserialize(obj) {
    const value = obj[valueKey];
    if (!Array.isArray(value)) {
      throw new Error('Expected Array, obtained: ' + value);
    }
    const result = new Map();
    for (let i = 0; i < value.length; i += 2) {
      result.set(this.reader.read(value[i]), this.reader.read(value[i + 1]));
    }
    return result;
  }

  /** @param {Map} map */
  serialize(map) {
    const arr = [];
    map.forEach((v, k) => {
      arr.push(this.writer.adaptObject(k));
      arr.push(this.writer.adaptObject(v));
    });
    return {
      [typeKey]: 'g:Map',
      [valueKey]: arr,
    };
  }

  canBeUsedFor(value) {
    return value instanceof Map;
  }
}

class ListSerializer extends ArraySerializer {
  constructor() {
    super('g:List');
  }
}

class SetSerializer extends ArraySerializer {
  constructor() {
    super('g:Set');
  }
}

module.exports = {
  BulkSetSerializer,
  BytecodeSerializer,
  DateSerializer,
  DirectionSerializer,
  EdgeSerializer,
  EnumSerializer,
  LambdaSerializer,
  ListSerializer,
  LongSerializer,
  MapSerializer,
  NumberSerializer,
  Path3Serializer,
  PathSerializer,
  PropertySerializer,
  PSerializer,
  TextPSerializer,
  SetSerializer,
  TSerializer,
  TraverserSerializer,
  TraversalStrategySerializer,
  typeKey,
  valueKey,
  VertexPropertySerializer,
  VertexSerializer,
};
