<template>
  <div class="address-block">
    <!-- address house name and postcode questions -->
    <template v-if="specificAddressFound === false && addressList.length === 0">
      <template v-if="manualAddress === false">
        <div class="question">
          <label>{{ housenumberLabel }}</label>
          <input name="house_number" id="house_number"
            placeholder="House or building number" 
            v-model="addressObject.houseNumber" 
            ref="housenumber"
            maxlength="12" />
        </div>

        <div class="question" :class="{ 
            'error': isValid == false, 
            'good': isValid == true
          }">
          <label>{{ postcodeLabel }}</label>
          <input name="postcode" id="postcode" class="uppercase" 
            v-model="addressObject.postcode"
            ref="postcode"
            maxlength="8"
            placeholder="Postcode"
            @blur="validate()" />
          <p class="error-message">{{ validationMessage }}</p>
          <button class="btn btn-secondary findAddress" @click="searchAddress()" v-show="!addressLoading">Find Address</button>

          <span class="info-message link" v-if="includeManual" @click="manualAddress = true">Or enter address manually</span> 

          <!-- LOADING IMAGE SLOT -->
          <div v-show="addressLoading">
            <slot></slot>
          </div>
        </div>
      </template>

      <!-- MANUAL ADDRESS ENTRY -->
      <div class="close-questions" v-if="manualAddress === true && includeManual">
        <span class="info-message link" @click="manualAddress = false">Use postcode lookup</span>

        <text-input label="Flat number"
           placeholder="Flat number"
           inputname="flat"
           :required="false"
           :maxLength="16"
           :value="{ value: addressObject.flat }"
           :textOnly="false"
           :customErrors="{
             required: 'Please enter your first name'
           }"
           :sectionID="sectionID + 0.1"
           v-on:validated="handleManualAddress($event)"
        />
        <text-input label="House name"
           placeholder="House name"
           inputname="houseName"
           :required="false"
           :maxLength="32"
           :value="{ value: addressObject.houseName }"
           :textOnly="false"
           :customErrors="{
             required: 'Please enter your first name'
           }"
           :sectionID="sectionID + 0.1"
           v-on:validated="handleManualAddress($event)"
        />
        <text-input label="House number"
           placeholder="House number"
           inputname="houseNumber"
           :required="addressObject.houseName === null"
           :maxLength="16"
           :value="{ value: addressObject.houseNumber }"
           :textOnly="false"
           :customErrors="{
             required: 'Please enter your house number or house name'
           }"
           :sectionID="sectionID + 0.1"
           v-on:validated="handleManualAddress($event)"
        />
        <text-input label="Street name"
           placeholder="Street name"
           inputname="streetName"
           :required="true"
           :maxLength="60"
           :value="{ value: addressObject.streetName }"
           :textOnly="true"
           :customErrors="{
             required: 'Please enter your street name'
           }"
           :sectionID="sectionID + 0.1"
           v-on:validated="handleManualAddress($event)"
        />
        <text-input label="Town"
           placeholder="Town"
           inputname="town"
           :required="true"
           :maxLength="32"
           :value="{ value: addressObject.town }"
           :textOnly="true"
           :customErrors="{
             required: 'Please enter your town or city name'
           }"
           :sectionID="sectionID + 0.1"
           v-on:validated="handleManualAddress($event)"
        />
        <text-input label="County"
           placeholder="County"
           inputname="county"
           :required="false"
           :maxLength="32"
           :value="{ value: addressObject.county }"
           :textOnly="true"
           :sectionID="sectionID + 0.1"
           v-on:validated="handleManualAddress($event)"
        />
        <text-input label="Postcode"
           placeholder="Postcode"
           inputname="postcode"
           :required="true"
           :maxLength="8"
           :value="{ value: addressObject.postcode }"
           :textOnly="false"
           :customErrors="{
             required: 'Please enter your postcode'
           }"
           :sectionID="sectionID + 0.1"
           v-on:validated="handleManualAddress($event)"
        />
        
        <button v-if="addressConfirmed === false"
            class="btn btn-secondary" 
            @click="confirmManual(sectionID + 0.1)">Confirm Address</button>
      </div>
    </template>

    <!-- address options -->
    <template v-else-if="specificAddressFound === false && addressList.length > 0">
      <div class="question">
        <label>Please select your address <span class="edit-address" @click="resetAddress()">Edit</span></label>
        <span class="input-select">
          <select
            v-model="selectedAddress" 
            placeholder="Please select..."
            @change="handleAddressSelection($event)"
            @focus="isValid = null">
            <option value="Please select..." :selected="selectedAddress === 'Please select...'" hidden>Please select...</option>
            <option 
              v-for="(address, index) in addressList" 
              :key="index +'-' + address.houseNumber + '-' + address.streetName"
              :value="index">
                 {{ (address.flat !== null && address.flat !== undefined && address.flat !== "") ? address.flat + ',' : '' }} 
                 {{ (address.houseName !== null && address.houseName !== undefined && address.houseName !== "") ? address.houseName + ',' : '' }} 
                 {{ (address.houseNumber !== null && address.houseNumber !== undefined && address.houseNumber !== "") ? address.houseNumber + ',' : '' }} 
                 {{ (address.streetName !== null && address.streetName !== undefined && address.streetName !== "") ? address.streetName + ',' : '' }} 
                 {{ (address.town !== null && address.town !== undefined && address.town !== "") ? address.town : '' }}
            </option>
          </select>
        </span>
      </div>
    </template>

    <!-- address result -->
    <template v-else-if="specificAddressFound === true">
      <h3 class="label">
        {{ label !== null && label !== undefined ? label : 'Your address' }}
        <span class="edit-address" @click="resetAddress()">Edit</span>
      </h3>
      <div class="selected-address good" style="display: block">
        <span v-show="addressObject.flat">{{ addressObject.flat }}</span>
        <span v-show="addressObject.houseName">{{ addressObject.houseName }}</span>
        <span v-show="(addressObject.streetName || addressObject.houseNumber)">{{ addressObject.houseNumber }} {{ addressObject.streetName }}</span>
        <span v-show="addressObject.town">{{ addressObject.town }}</span>
        <span v-show="addressObject.county">{{ addressObject.county }}</span>
        <span class="uppercase">{{ addressObject.postcode }}</span>
        <span>{{ addressObject.country }}</span>
      </div>

      <!-- lived three years -->
      <template v-if="yearsRequired !== null && yearsRequired !== undefined && yearType === 'buttons'">
        <buttons-radio
          :label="'Have you lived at this address for ' + yearsRequired + ' or more years?'"
          :inputname="inputname + '-years'"
          :required="true"
          :options="[
            { name: 'Yes', value: 'true' },
            { name: 'No', value: 'false' }
          ]"
          :sectionID="sectionID"
          :columnCount="2"
          v-on:validated="calculateMoveInButtons($event)"
        />
      </template>
      <template v-else-if="yearsRequired !== null && yearsRequired !== undefined && yearType === 'text'">
          <number-input label="How many years have you lived at this address?"
            placeholder="Years"
            :inputname="inputname + '-years'"
            :required="true"
            :minLength="1"
            :maxLength="2"
            :sectionID="sectionID + 0.2"
            :customErrors="{
              required: 'Please tell us how many years you\'ve lived at this address'
            }"
            :disabled="addressConfirmed"
            ref="yearsInput"
          />
          <button v-if="addressConfirmed === false"
            class="btn btn-secondary" 
            @click="calculateMoveInText()">Confirm Address</button>
      </template>
    </template>
  </div>
</template>

<script>
// create event hub for validation events
import Vue from 'vue'

import ButtonsRadio from './buttons-radio.vue'
import TextInput from './textinput.vue'
import NumberInput from './numberinput.vue'

import axios from 'axios'
const moment = require('moment')

import vRules from 'vanilla-validation'
import { validation } from '../mixins/validation.js'

export default {
  name: 'addressblock',
  components: {
    ButtonsRadio,
    NumberInput,
    TextInput
  },
  mixins: [validation],
  props: {
    inputname: {
      type: String,
      required: true
    },
    label: String,
    housenumberLabel: {
      type: String,
      default: 'House or building number'
    },
    postcodeLabel: {
      type: String,
      default: 'Postcode'
    },
    required: Boolean,
    value: Object,
    yearsRequired: Number,
    yearType: {
      type: String,
      default: 'buttons'
    },
    includeManual: {
      type: Boolean,
      default: false
    },
    lookupAPIURL: String,
    helpText: String,
    sectionID: Number,
    previousAddress: Object,
    // this is used to return fake addresses
    // when in test/dev mode
    isTesting: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      // object containing all data for address
      addressObject:  {
        "flat": null,
        "houseNumber": null,
        "houseName": null,
        "streetName": null,
        "district": null,
        "town": null,
        "county": null,
        "postcode":null,
        "ptcabsCode": null,
        "movedIn": null,
      },
      // used for manual address entry
      manualAddress: false,
      // array containing list of addresses - populated via API
      addressList: [],
      // boolean to confirm if an address has been found
      specificAddressFound: false,
      // used to hold the value of address in select box
      selectedAddress: 'Please select...',
      // used to show/hide 'confirm address' button
      addressConfirmed: false,
      // used to show/hide loading animation
      addressLoading: false,

      // years at address used by text input type
      yearsAtAddress: null
    }
  },
  created() {
    // We listen for the event on the eventHub
    this.$eventHub.on('validate', (id) => {
      // if validating by section
      if (this.sectionID != undefined) {
          // if the id provided matches section ID then validate
          if (id === this.sectionID) {
            this.validate()
          }
      } else {
        // if not validating by section
        this.validate()
      }
    })
    // if prepopulating set data
    if (this.value !== undefined) {
        this.inputValue = this.value.value
    }
  },
  methods: {
    validate(){
      var postcodeInput = this.$refs.postcode

      // check what validations are required
      // and build and array of booleans (these are then checked to see if input is valid)
      let result_postcode = [
        vRules.vrule_required(postcodeInput),
        vRules.vrule_postcode(postcodeInput),
      ]
      
      // check validation result
      // this function is imported from validation mixin
      // if will set the valid status and error message
      this.setValidationStatus(result_postcode)
    },
    // search postcode and handle result
    searchAddress: function () {
      // validate the postcode
      this.validate()

      if (this.isValid === true) {
        // set loading to true
        this.addressLoading = true
        // call api
        axios.get(this.lookupAPIURL + this.addressObject.postcode)
        .then(response => {
            this.addressLoading = false
            this.handleAddress(response.data, this.addressObject.houseNumber)
        })
        .catch(error => {
          console.error(error);
          this.addressLoading = false
          // if the http get call fails
          // check if we're in test mode
          // and if so return default address
          if (this.isTesting === true) {
            this.handleAddress([
              {
                  "houseNumber": "18",
                  "streetName": "High Street",
                  "town": "Westbury",
                  "county": "Wiltshire",
                  "postcode": "BA133BN",
                  "ptccode": "58150004076"
              }
            ], this.addressObject.houseNumber)
          } else {
            this.validationMessage = "No addresses found, please check you entered your postcode correctly"
            this.isValid = false
          }
          
        })
      }
    },
    // handle address API result
    handleAddress: function (addresses, housenumber) {
      let tempAddressList = []
      let tempAddressListMatched = []
      // used when a house number is provided
      // to try and find absolute address rather than returning the full list
      if (housenumber !== undefined) {
        addresses.forEach((address) => {
          // return the address
          if (housenumber !== null && address.houseNumber === housenumber) {
            // check the address found is not a flat
            if (address.flat === null || address.flat === undefined || address.flat === '') {
              // set the address object based on API result
              // with matching house number
              this.addressObject = address

              this.specificAddressFound = true
              if (this.yearsRequired === null || this.yearsRequired === undefined) {
                if (this.yearType === 'buttons') {
                  this.calculateMoveInButtons()
                } else {
                  this.calculateMoveInText()
                }
              }
              return
            } else {
              // if address found is a flat push this to the temp address list
              tempAddressListMatched.push(address)
            }
          } else if (addresses.length === 1) {
            // only 1 address found
            // set this as selected address
            this.addressObject = address

            this.specificAddressFound = true
            if (this.yearsRequired === null || this.yearsRequired === undefined) {
              if (this.yearType === 'buttons') {
                this.calculateMoveInButtons()
              } else {
                this.calculateMoveInText()
              }
            }
            return
          } else {
            // no matching address found
            // push all addresses to temp address list
            tempAddressList.push(address)
          }
        })
      }
      // if no house number provided or no match found
      // return all addresses
      this.addressList = tempAddressListMatched.length > 0 ? tempAddressListMatched : tempAddressList
    },
    // handle address when selected from dropdown
    handleAddressSelection: function (event) {
      let selectedAddress = this.addressList[event.target.value]
      // set the address object based on API result
      // with matching house number
      this.addressObject = selectedAddress
      
      this.specificAddressFound = true

      if (this.yearsRequired === null || this.yearsRequired === undefined) {
        if (this.yearType === 'buttons') {
          this.calculateMoveInButtons()
        } else {
          this.calculateMoveInText()
        }
      }
    },
    handleManualAddress: function (result) {
      this.$set(this.addressObject, result.name, result.value)
    },
    confirmManual: function (sectionID) {
      this.$eventHub.emit('validate', sectionID)

      let houseNoOrName = this.addressObject.houseNumber !== null || this.addressObject.houseName !== null
      let street = this.addressObject.street !== null
      let town = this.addressObject.town !== null
      let postcode = this.addressObject.postcode !== null

      if (houseNoOrName && street && town && postcode) {
        this.specificAddressFound = true
      }
    },
    calculateMoveInButtons: function (event) {
      // default address date to 3 years from today
      // if we ask for specific number of years we update to use this value
      let approxDate = moment().subtract(3, 'years')

      // check that we're asking for a set number of years
      if (this.yearsRequired !== null && this.yearsRequired !== undefined) {
        console.log('event.value', event)
        // check if user has lived at address required years
        this.addressObject.lived_for_required_years = (event.value === true)

        // calculate approximate move in date
        approxDate = this.addressObject.lived_for_required_years ? 
                    moment().subtract(this.yearsRequired, 'years') : 
                    moment().subtract(2, 'years')
      } else {
        this.addressObject.lived_for_required_years = true
      }
      

      // set address object move in date
      this.addressObject.movedIn = moment(approxDate).format("YYYY/MM/DD") 

      // confirm the address
      this.confirmAddress(true)
    },
    calculateMoveInText: function () {
      this.$eventHub.$emit('validate', this.sectionID + 0.2)

      const yearsInput = this.$refs.yearsInput

      if (yearsInput.isValid) {
        // get inputValue variable from custom number input type
        let yearsAtAddressValue = Number(yearsInput.inputValue)
        
        // if this is a second address then we need to set a start date based on the previous address
        let startDate = this.previousAddress !== undefined ? 
                        moment(this.previousAddress.movedIn, "YYYY/MM/DD") : // previous move in date 
                        moment() // current date
        
        let approxDate = startDate.subtract(yearsAtAddressValue, 'years')

        // check that we're asking for a set number of years
        if (this.yearsRequired !== null && this.yearsRequired !== undefined) {
          // check if user has lived at address required years
          this.addressObject.lived_for_required_years = (yearsAtAddressValue >= this.yearsRequired)   
        } else {
          this.addressObject.lived_for_required_years = true
        }

        // set address object move in date
        this.addressObject.movedIn = moment(approxDate).format("YYYY/MM/DD") 

        // confirm the address
        this.confirmAddress(true)
      }
    },
    confirmAddress: function (valid) {
      this.addressConfirmed = valid
      // emit addressConfirmed event
      this.$emit('addressConfirmed', { 
        'value': this.addressObject, 
        'name': this.inputname, 
        'isValid': valid
      })
    },
    resetAddress: function () {
      this.addressConfirmed = false
      this.specificAddressFound = false
      this.addressList = []
      this.selectedAddress = 'Please select...'
      this.isValid = null
      this.addressObject = {
        "flat": null,
        "houseNumber": null,
        "houseName": null,
        "streetName": null,
        "district": null,
        "town": null,
        "county": null,
        "postcode":null,
        "ptcabsCode": null,
        "movedIn": null
      }
      // confirm the address
      this.confirmAddress(false)
    }  
  }
}
</script>
