/**
 * Judge Class Application
 *
 * @package    Portal
 * @category   Application
 * @author     Everett Myers <Everett@AllSportsEquine.com>
 * @copyright  2013-2021 All Sports Equine, All Rights Reserved
 * @link       https://www.AllSportsEquine.com/portal/AReact/Application.html
 * @version    1.0.0 2021-03-04
 */

// -------------------------------------------------------------------------------------------------

/**
 * Judge Class Application
 *
 * This is the base or root application for the portal.
 *
 */
class JudgeClassApp extends App {

  /**
   * Constructor
   *
   * The constructor for a React component is called before it is mounted. When
   * implementing the constructor for a React.Component subclass, you should
   * call super(props) before any other statement. Otherwise, this.props will be
   * undefined in the constructor, which can lead to bugs. The initialized state
   * will be set to FALSE with initializing being added to waiting state to
   * ensure initialize() will be called after componentDidMount().
   *
   * @param object props
   *
   * @return void
   */
  constructor(props) {

    // =========================================================================
    // DEBUG
    // =========================================================================
    if (appDebug.includes('lifecycle')) {
      console.log('JudgeClassApp.constructor()',{props:props})
    }

    // =========================================================================
    // PARENT
    // =========================================================================
    super(props)

    // =========================================================================
    // PARENT APP LINKS (note DO NOT link states here)
    // =========================================================================
    this.MainApp  = props.parentApp.MainApp
    this.JudgeApp = props.parentApp.JudgeApp

    // =========================================================================
    // SET THIS STATE
    // =========================================================================
    Object.assign(this.state, {
      class_id:     0
    , classObject:  null
    , not_found:    false
    })

    // =========================================================================
    // URL PATHS (things that DO NOT CHANGE this instance)
    // =========================================================================
    this.url_paths = Object.assign({
      route_base:       props.parentApp.url_paths.route_base+'/'+CONFIG.classes_uri
    , show_route_base:  props.parentApp.url_paths.route_base
    , class:            props.parentApp.url_paths.classes+'/'+parseInt(props.parentMatch.params.class_id)
    }, props.parentApp.url_paths)

    // =========================================================================
    // CLASS ID WAS PASSED
    // =========================================================================
    if (typeof props.parentMatch.params.class_id !== 'undefined') {
      this.state.class_id = parseInt(props.parentMatch.params.class_id)
    }

  }

  /**
   * Initialize
   *
   * initialize() is invoked following a standard componentDidMount() call. It
   * may also be invoked following componentDidUpdate() if the current
   * initialized state is set to FALSE.
   *
   * This is a good place to load data from the API and check for changed props
   * from the parent. Until this method has completed a waiting for initializing
   * will be in place. This is normally extended in each child.
   *
   * @param callback callback optional
   *
   * @return Promise
   */
  initialize(callback) {

    // =========================================================================
    // SET OPTIONAL ARGUMENTS (if not passed)
    // =========================================================================
    if(typeof(callback) !== "function") var callback = () => {}

    // =========================================================================
    // DEBUG
    // =========================================================================
    if (appDebug.includes('lifecycle')) {
      console.log('JudgeClassApp.initialize()')
    }

    // =========================================================================
    // GET PARENT STATES ITEMS
    // =========================================================================
    const showObject = this.JudgeApp.state.showObject

    // =========================================================================
    // FIND CLASS
    // =========================================================================
    var found = false
    showObject.classes.forEach( classObject => {
      if (classObject.class_id == this.state.class_id) {
        found = true

      // -------------------------------------------------------------------
      // LOAD PATTERNS
      // -------------------------------------------------------------------
        if (typeof classObject.patterns === 'undefined') {
          classObject.patterns = []
          
          // API OPTIONS
          const options = {
            filters:  {
              include_children: 'elements'
            , elements_include_children: 'marks'
            }
          }

          classObject.getSubResource('patterns', 'PatternModel', options).then(
            patterns => {
              classObject.patterns = patterns
              this.waitingEnd('initializing', {
                classObject:  classObject
              , not_found:    false
              , initialized:  true
              })

            }
          )

      // -------------------------------------------------------------------
      // PATTERNS ALREADY LOADED
      // -------------------------------------------------------------------
        } else {
          this.waitingEnd('initializing', {
            classObject:  classObject
          , not_found:    false
          , initialized:  true
          })
        }
      }
    })

    // =========================================================================
    // Not Found
    // =========================================================================
    if (found == false) {
      this.waitingEnd('initializing', {
        not_found:   true
      , initialized: true
      })
    }

  }

  // ---------------------------------------------------------------------------------------------

  /**
   * Render
   *
   * The render() method is used to create new elements for the DOM. This is
   * normally where the main <Switch> and <Route> elements are placed for this
   * application.
   *
   * @return <element>
   */
  render() {

    // =========================================================================
    // DEBUG
    // =========================================================================
    if (appDebug.includes('lifecycle')) {
      console.log('JudgeClassApp.render()')
    }

    // =========================================================================
    // RENDER REDIRECT/LOADING
    // =========================================================================
    const parentRender = super.render()
    if (parentRender != null) {
      return parentRender
    }

    // =========================================================================
    // NOT FOUND
    // =========================================================================
    if (this.state.not_found) {
      return this.renderNotFound()
    }

    // =========================================================================
    // GET PARENT STATES ITEMS
    // =========================================================================
    const classObject = this.state.classObject

    // =========================================================================
    // ACCOUNT NOT LOADED OR NOT INITIALIZED
    // =========================================================================
    if (classObject == null) {
      return this.renderLoading(null, 'JudgeClassApp.classObject')
    }

    // =========================================================================
    // BASE URIs
    // =========================================================================
    const base_entry   = this.url_paths.class+'/entries/:entry_id'
    const base_pattern = this.url_paths.class+'/patterns/:pattern_id'

    // =========================================================================
    // RENDER
    // =========================================================================
    return (
      <Switch>

        <Route path={this.url_paths.class+'.html'} render={ p => {
          switch (this.state.classObject.class_variety.scoring_method) {
            case "by_team":
            default:
              return this.renderEntryList(p)
              break
            case "by_pattern":
              return this.renderPatternList(p)
              break
          }
        }} />

        <Route path={base_entry+'.html'} render={ p =>
          <JudgeEntryApp parentApp={this} parentMatch={p.match} />
        }/>
        <Route path={base_entry+'/'} render={ p =>
          <JudgeEntryApp parentApp={this} parentMatch={p.match} />
        }/>
        <Route path={base_pattern+'.html'} render={ p =>
          <JudgePatternApp parentApp={this} parentMatch={p.match} />
        }/>
        <Route path={base_pattern+'/'} render={ p =>
          <JudgePatternApp parentApp={this} parentMatch={p.match} />
        }/>

        <Route path="*" render={ p => this.renderNotFound(p)} />
      </Switch>
    )

  }

  /**
   * Render Entry List
   *
   * @return <element>
   */
  renderEntryList(props) {

    // =========================================================================
    // DEBUG
    // =========================================================================
    if (appDebug.includes('lifecycle')) {
      console.log('JudgeClassApp.renderEntryList()')
    }

    // =========================================================================
    // GET PARENT STATES ITEMS
    // =========================================================================
    const showObject  = this.JudgeApp.state.showObject
    const classObject = this.state.classObject
    const userObject = this.state.userObject

    // =========================================================================
    // HELPERS
    // =========================================================================
    const table = new ReactTable()

    if ( ! this.MainApp.state.accountObject) {
      return this.renderLoading(null, 'JudgeShowApp.renderClassList')
    }

    // =========================================================================
    // ASSIGNED ENTRY TYPES TO JUDGE
    // =========================================================================
    const assigned_entry_types = [] 
    classObject.entries.forEach( (entryObject, index) => {
      const assigned = classObject.judges.some( judgeObj => {
        if (entryObject.type_id != judgeObj.entry_type_id) return false
        if (classObject.class_variety.multiple_judges) {
          return this.MainApp.state.accountObject.hasJudge(judgeObj.judge_id)
        }
        return true
      })
      if (assigned == false) return
      assigned_entry_types.push(entryObject)
    })

    var hide_cols = []
    if ( ! showObject.config.has_videos) {
      hide_cols.push('video')
    }
    if ( ! showObject.config.has_rider_numbers) {
      hide_cols.push('rider_number')
    }
    hide_cols.push('entry_id')

    const judgeObj = this.MainApp.state.accountObject.participants.find( obj => obj.participant_id == this.MainApp.state.accountObject.selected_judge_id )

    // =========================================================================
    // RENDER
    // =========================================================================
    return (
     <div className="event-list">
        <div className="page-header">
          <h1>
            {showObject.name}<br />
            <span>{classObject.class_variety.name}</span><br />
            <span>{classObject.dateFormat('long')}</span>
          </h1>
          <h2>
            <i
              className="fad fa-arrow-alt-square-left fa-button-action"
              onClick={ () => {
                this.transitionTo(this.url_paths.show+'.html')
              }}
            ></i>
            <div className="judge-select">
              Judge: {judgeObj.first_name} {judgeObj.last_name}
            </div>
          </h2>
        </div>
        <table className="default">
          <thead>
            <tr>
              <th colSpan="999" className="large-title">Entries</th>
            </tr>
          </thead>
          {table.renderTableHeader(CONFIG.judge_entries_table.columns, null, hide_cols)}
          <tbody className="alt-tr">
            {assigned_entry_types.map( (entryObject, index) => {
              let can_score = true
              let cannot_score_text = ''
              if (entryObject.canceled) {
                cannot_score_text = 'Canceled'
                can_score = false
              }
              if (entryObject.no_show) {
                cannot_score_text = 'No Show'
                can_score = false
              }
              if (!can_score) {
                return (
                  <tr
                    key={index}
                    className="event-list"
                    title={can_score?'':cannot_score_text}
                  >
                    {showObject.config.has_rider_numbers != false &&
                        <td className="align-center">{entryObject.number}</td>
                    }
                    <td className="align-left">{entryObject.entry_type.name}</td>
                    <td className="align-center">{entryObject.division.name}</td>
                    <td className="align-left">{entryObject.participant.first_name}</td>
                    <td className="align-left">{entryObject.participant.last_name}</td>
                    <td className="align-left">{entryObject.equinePreferredName('barn_name')}</td>
                    {showObject.config.has_videos &&
                        <td className="align-center">
                          {entryObject.video_link &&
                            <i className="fas fa-check-circle"></i>
                          }
                        </td>
                    }
                    <td className="align-center">{cannot_score_text}</td>
                  </tr>
                )
              }
              return (
                <tr
                  key={index}
                  className="event-list on-click"
                  onClick={ () => {
                    this.transitionTo(`${this.url_paths.class}/entries/${entryObject.entry_id}.html?judge_id=${this.MainApp.state.accountObject.selected_judge_id}`)
                  }}
                >
                  {table.renderTableRow(CONFIG.judge_entries_table.columns, entryObject, this.state, hide_cols)}
                </tr>
              )
            })}
          </tbody>
          {(assigned_entry_types.length == 0) && (
            <tfoot>
              <tr className="no-results">
                <td className="align-center" colSpan={CONFIG.judge_entries_table.columns.length}>No Entries Found</td>
              </tr>
            </tfoot>
          )}
        </table>
      </div>
    )
  
  }

  /**
   * Render Pattern List
   *
   * @return <element>
   */
  renderPatternList(props) {

    // =========================================================================
    // DEBUG
    // =========================================================================
    if (appDebug.includes('lifecycle')) {
      console.log('JudgeClassApp.renderPatternList()')
    }

    // =========================================================================
    // GET PARENT STATES ITEMS
    // =========================================================================
    const showObject  = this.JudgeApp.state.showObject
    const classObject = this.state.classObject
    const userObject = this.state.userObject

    // =========================================================================
    // HELPERS
    // =========================================================================
    const table = new ReactTable()

    // =========================================================================
    // ASSIGNED ENTRY TYPES TO JUDGE
    // =========================================================================
    const assigned_patterns = [] 
    classObject.patterns.forEach( (patternObject, index) => {
      let assigned = false
      if (classObject.class_variety.multiple_judges) {
        assigned = classObject.judges.some( judgeObj => {
          if (patternObject.pattern_id != judgeObj.pattern_id) return false
          return this.MainApp.state.accountObject.hasJudge(judgeObj.judge_id)
        })
      } else {
        assigned = true
      }
      if (assigned == false) return
      assigned_patterns.push(patternObject)
    })

    var hide_cols = []

    // =========================================================================
    // RENDER
    // =========================================================================
    return (
     <div className="event-list">
        <div className="page-header">
          <h1>
            {showObject.name}<br />
            <span>{classObject.class_variety.name}</span><br />
            <span>{classObject.dateFormat('long')}</span>
          </h1>
          <h2>
            <i
              className="fad fa-arrow-alt-square-left fa-button-action"
              onClick={ () => {
                this.transitionTo(this.url_paths.show+'.html')
              }}
            ></i>
          </h2>
        </div>
        <table className="default">
          <thead>
            <tr>
              <th colSpan="999" className="large-title">Patterns</th>
            </tr>
          </thead>
          {table.renderTableHeader(CONFIG.judge_patterns_table.columns, null, hide_cols)}
          <tbody className="alt-tr">
            {assigned_patterns.map( (patternObject, index) => { return (
              <tr
                key={index}
                className="event-list on-click"
                onClick={ () => {
                  this.transitionTo(this.url_paths.class+'/patterns/'+patternObject.pattern_id+'.html')
                }}
              >
                {table.renderTableRow(CONFIG.judge_patterns_table.columns, patternObject, this.state, hide_cols)}
              </tr>
            )})}
          </tbody>
          {(assigned_patterns.length == 0) && (
            <tfoot>
              <tr className="no-results">
                <td className="align-center" colSpan={CONFIG.judge_patterns_table.columns.length}>No Patterns Found</td>
              </tr>
            </tfoot>
          )}
        </table>
      </div>
    )
  
  }

}

// EOF /////////////////////////////////////////////////////////////////////////////////////////////
