import { Extensions, GPXBuildData } from '../../types';
import * as models from './models';
import { Metadata, Point, Segment, Track, Route } from './models';

export default class BaseBuilder {
  protected data: GPXBuildData;

  protected schemaLocation: string[];

  public static MODELS = models;

  public constructor() {
    this.data = {};
    this.schemaLocation = [
      'http://www.topografix.com/GPX/1/1',
      'https://www.topografix.com/GPX/1/1/gpx.xsd',
    ];
  }

  /**
   * Set metadata object.
   *
   * @param metadata - Metadata object
   * @returns {BaseBuilder} self
   */
  public setMetadata(metadata: Metadata): this {
    this.data.metadata = metadata.toObject();
    return this;
  }

  /**
   * Set list of waypoints
   *
   * @param waypoints - Points objects
   * @returns {BaseBuilder} self
   */
  public setWayPoints(waypoints: Point[]): this {
    this.data.wpt = waypoints.map((point) => point.toObject());
    return this;
  }

  /**
   * Set list of routes.
   *
   * @param routes - List of routes
   * @returns {BaseBuilder} self
   */
  public setRoutes(routes: Route[]): this {
    this.data.rte = routes.map((route) => route.toObject());
    return this;
  }

  /**
   * Set list of tracks.
   *
   * @param tracks - List of tracks
   * @returns {BaseBuilder} self
   */
  public setTracks(tracks: Track[]): this {
    this.data.trk = tracks.map((track) => track.toObject());
    return this;
  }

  /**
   * Set extension Object.
   *
   * @param extensions - Extensions
   * @returns {BaseBuilder} self
   */
  public setExtensions(extensions: Extensions): this {
    this.data.extensions = extensions;
    return this;
  }

  /**
   * Simple method to set list of points to single track and segment.
   *
   * @param points - list of Points
   * @returns {BaseBuilder} self
   */
  public setSegmentPoints(points: Point[]): this {
    this.setTracks([new Track([new Segment(points)])]);
    return this;
  }

  /**
   * Object that can be used to build XML file.
   *
   * @returns {GPXBuildData}
   */
  public toObject(): GPXBuildData {
    return {
      ...this.data,
      attributes: {
        creator: 'fabulator:gpx-builder',
        version: '1.1',
        xmlns: 'http://www.topografix.com/GPX/1/1',
        'xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance',
        'xsi:schemaLocation': this.schemaLocation.join(' '),
        ...this.data.attributes,
      },
    };
  }
}
