'use strict';

const config = require('@dwaring87/config');
const path = require('path');

/**
 * Right Track Transit Agency Abstract Class
 * @see {@link RightTrackTransitAgency}
 * @module classes/RightTrackTransitAgency
 */


/**
 * ### `RightTrackTransitAgency` Abstract Class
 * 
 * This module provides the abstract class for all implementing 
 * Transit Agencies.  It provides methods for managing the Transit Agency 
 * configuration, getting the required configuration properties, and loading
 * a Transit Feed for the Transit Agency. 
 * 
 * **Module:** {@link module:classes/RightTrackTransitAgency|classes/RightTrackTransitAgency}
 *
 * @class
 * @alias RightTrackTransitAgency
 * @abstract
 */
class RightTrackTransitAgency {

  /**
   * Abstract Transit Agency class constructor.  The implementing transit agency 
   * should call this constructor with the path to its own module directory:
   * `super(moduleDirectory)` in order to read the default agency configuration 
   * and set the intial configuration properties.
   * 
   * Each implementing Transit Agency should include (at least) the following 
   * properties in its agency config file:
   * - id: Transit Agency ID Code
   * - name: Transit Agency Display Name
   * - description: Transit Agency Description
   * - iconPath: Local file path to the Transit Agency icon
   * - maintainer: Transit Agency maintainer information:
   *    - name: Maintainer name
   *    - email: Maintainer email address
   *    - source: Maintainer's project source address
   * The Transit Agency config file may contain any additional properties that it 
   * may need (ie for the Transit Feed, etc).
   * 
   * @param {string} moduleDirectory The full path to the root of the transit 
   * agency's module directory.  This is where any relative paths to configuration 
   * files will be relative to.
   */
  constructor(moduleDirectory) {

    // Set Transit Agency Moduel Directory
    this._moduleDirectory = moduleDirectory;

    // Setup Config
    this._config = new config(path.normalize(this._moduleDirectory + '/agency.json'));

  }


  // ==== CLASS MEMBERS ==== //

  /**
   * The Transit Agency's module directory
   * @returns {string}
   */
  get moduleDirectory() {
    return path.normalize(this._moduleDirectory);
  }

  /**
   * The Transit Agency's configuration properties
   * @returns {Object}
   */
  get config() {
    return this._config.get();
  }

  /**
   * Transit Agency's id code
   * @returns {string}
   */
  get id() {
    return this.config.id;
  }

  /**
   * The Transit Agency's full name
   * @returns {string}
   */
  get name() {
    return this.config.name;
  }

  /**
   * The Transit Agency's description
   * @returns {string}
   */
  get description() {
    return this.config.description;
  }

  /**
   * The Transit Agency's maintainer information
   * @returns {Object}
   */
  get maintainer() {
    return this.config.maintainer;
  }


  // ==== CONFIGURATION ==== //

  /**
   * Reset the transit agency configuration to the default values
   */
  resetConfig() {
    this._config.reset();
  }

  /**
   * Read an additional transit agency configuration file
   * @param {string} configFile Path to transit agency configuration file.
   * Relative paths will be relative to the root of the transit agency's module directory.
   */
  readConfig(configFile) {
    if ( !path.isAbsolute(configFile) ) {
      configFile = path.normalize(this.moduleDirectory + '/' + configFile);
    }
    this._config.read(configFile);
  }

  /**
   * Get the transit agency configuration
   * @returns {object} Transit Agency configuration
   */
  getConfig() {
    return this.config;
  }

 
  // ==== TRANSIT FEED ==== //

  /**
   * Load the Transit Feed for this Transit Agency
   * @param {function} callback Callback function
   * @param {Error} callback.error Transit Feed Error.  The Error's message will be
   * a pipe (`|`) separated string in the format of: `Error Code|Error Type|Error Message`
   * that will be parsed out by the **Right Track API Server** into a more specific
   * error Response.
   * @param {TransitFeed} [callback.feed] The built `TransitFeed` for the Transit Agency
   * @abstract
   */
  loadFeed(callback) {
    return callback(new Error("4052|Transit Feed Not Supported|This transit agency (" + this.name + ") does not support real-time Transit Feeds"));
  }

  /**
   * Get the matching Transit Division from the Agency's Transit Feed
   * @param {String[]} divisionCodes List of Transit Division codes (in hierarchical order)
   * @param {function} callback Callback function
   * @param {Error} callback.error Transit Feed Error
   * @param {TransitDivision} [callback.division] The matching `TransitDivision`
   */
  getDivision(divisionCodes, callback) {
    this.loadFeed(function(err, feed) {
      if ( err ) {
        return callback(err);
      }
      let division = undefined;
      let divs = feed.divisions;
      for ( let i = 0; i < divisionCodes.length; i++ ) {
        for ( let j = 0; j < divs.length; j++ ) {
          if ( divs[j].code === divisionCodes[i] ) {
            if ( i === divisionCodes.length-1 ) division = divs[j];
            divs = divs[j].divisions;
            break;
          }
        }
      }
      return callback(null, division);
    });
  }
  
}

module.exports = RightTrackTransitAgency;