import {
  EdgeCollection,
  _BaseCollection as BaseCollection,
  _types as types
} from './collection';

class GraphVertexCollection extends BaseCollection {
  constructor(connection, name, graph) {
    super(connection, name);
    this.type = types.DOCUMENT_COLLECTION;
    this.graph = graph;
    this._gharial = this._api.route(`gharial/${this.graph.name}/vertex/${this.name}`);
  }

  _documentPath(documentHandle) {
    return `document/${this._documentHandle(documentHandle)}`;
  }

  vertex(documentHandle, cb) {
    const {promise, callback} = this._connection.promisify(cb);
    this._gharial.get(
      documentHandle,
      (err, res) => err ? callback(err) : callback(null, res.body)
    );
    return promise;
  }

  save(data, cb) {
    const {promise, callback} = this._connection.promisify(cb);
    this._gharial.post(
      data,
      {collection: this.name},
      (err, res) => err ? callback(err) : callback(null, res.body)
    );
    return promise;
  }
}

class GraphEdgeCollection extends EdgeCollection {
  constructor(connection, name, graph) {
    super(connection, name);
    this.type = types.EDGE_COLLECTION;
    this.graph = graph;
    this._gharial = this._api.route(`gharial/${this.graph.name}/edge/${this.name}`);
  }

  edge(documentHandle, cb) {
    const {promise, callback} = this._connection.promisify(cb);
    this._gharial.get(
      documentHandle,
      (err, res) => err ? callback(err) : callback(null, res.body)
    );
    return promise;
  }

  save(data, fromId, toId, cb) {
    if (typeof fromId === 'function') {
      cb = fromId;
      fromId = undefined;
    } else if (fromId) {
      data._from = this._documentHandle(fromId);
      data._to = this._documentHandle(toId);
    }
    const {promise, callback} = this._connection.promisify(cb);
    this._gharial.post(
      data,
      (err, res) => err ? callback(err) : callback(null, res.body)
    );
    return promise;
  }
}

export default class Graph {
  constructor(connection, name) {
    this.name = name;
    this._connection = connection;
    this._api = this._connection.route('_api');
    this._gharial = this._api.route(`gharial/${this.name}`);
  }

  get(cb) {
    const {promise, callback} = this._connection.promisify(cb);
    this._gharial.get(
      (err, res) => err ? callback(err) : callback(null, res.body.graph)
    );
    return promise;
  }

  create(properties, cb) {
    if (typeof properties === 'function') {
      cb = properties;
      properties = undefined;
    }
    const {promise, callback} = this._connection.promisify(cb);
    this._api.post(
      'gharial',
      {...properties, name: this.name},
      (err, res) => err ? callback(err) : callback(null, res.body.graph)
    );
    return promise;
  }

  drop(dropCollections, cb) {
    if (typeof dropCollections === 'function') {
      cb = dropCollections;
      dropCollections = undefined;
    }
    if (typeof dropCollections !== 'boolean') dropCollections = false;
    const {promise, callback} = this._connection.promisify(cb);
    this._gharial.delete(
      {dropCollections},
      (err, res) => err ? callback(err) : callback(null, res.body)
    );
    return promise;
  }

  vertexCollection(collectionName) {
    return new GraphVertexCollection(this._connection, collectionName, this);
  }

  addVertexCollection(collectionName, cb) {
    const {promise, callback} = this._connection.promisify(cb);
    this._gharial.post(
      'vertex',
      {collection: collectionName},
      (err, res) => err ? callback(err) : callback(null, res.body.graph)
    );
    return promise;
  }

  removeVertexCollection(collectionName, dropCollection, cb) {
    if (typeof dropCollection === 'function') {
      cb = dropCollection;
      dropCollection = undefined;
    }
    const {promise, callback} = this._connection.promisify(cb);
    if (typeof dropCollection !== 'boolean') dropCollection = false;
    this._gharial.delete(
      `vertex/${collectionName}`,
      {dropCollection},
      (err, res) => err ? callback(err) : callback(null, res.body.graph)
    );
    return promise;
  }

  edgeCollection(collectionName) {
    return new GraphEdgeCollection(this._connection, collectionName, this);
  }

  addEdgeDefinition(definition, cb) {
    const {promise, callback} = this._connection.promisify(cb);
    this._gharial.post(
      'edge',
      definition,
      (err, res) => err ? callback(err) : callback(null, res.body.graph)
    );
    return promise;
  }

  replaceEdgeDefinition(definitionName, definition, cb) {
    const {promise, callback} = this._connection.promisify(cb);
    this._api.put(
      `gharial/${this.name}/edge/${definitionName}`,
      definition,
      (err, res) => err ? callback(err) : callback(null, res.body.graph)
    );
    return promise;
  }

  removeEdgeDefinition(definitionName, dropCollection, cb) {
    if (typeof dropCollection === 'function') {
      cb = dropCollection;
      dropCollection = undefined;
    }
    const {promise, callback} = this._connection.promisify(cb);
    if (typeof dropCollection !== 'boolean') dropCollection = false;
    this._gharial.delete(
      `edge/${definitionName}`,
      {dropCollection},
      (err, res) => err ? callback(err) : callback(null, res.body.graph)
    );
    return promise;
  }

  traversal(startVertex, opts, cb) {
    if (typeof opts === 'function') {
      cb = opts;
      opts = undefined;
    }
    const {promise, callback} = this._connection.promisify(cb);
    this._api.post(
      'traversal',
      {...opts, startVertex, graphName: this.name},
      (err, res) => err ? callback(err) : callback(null, res.body.result)
    );
    return promise;
  }
}

export {
  GraphVertexCollection as VertexCollection,
  GraphEdgeCollection as EdgeCollection
};

@@ -477,24 +477,268 @@
 ndle)%7D%60;%0A  %7D
+%0A  %0A  remove(documentHandle, cb) %7B%0A    const %7Bpromise, callback%7D = this._connection.promisify(cb);%0A    this._gharial.delete(%0A      documentHandle,%0A      (err, res) =%3E err ? callback(err) : callback(null, res.body)%0A    );%0A    return promise;%0A  %7D
 %0A%0A  vertex(d
@@ -1485,24 +1485,268 @@
 name%7D%60);%0A  %7D
+%0A  %0A  remove(documentHandle, cb) %7B%0A    const %7Bpromise, callback%7D = this._connection.promisify(cb);%0A    this._gharial.delete(%0A      documentHandle,%0A      (err, res) =%3E err ? callback(err) : callback(null, res.body)%0A    );%0A    return promise;%0A  %7D
 %0A%0A  edge(doc

Add Graph API remove method to Graph collections