import React, { useState, forwardRef } from 'react'
import { ErrorMessage, useField, Field } from 'formik'
import DatePicker from 'react-datepicker'
import moment from 'moment'
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"

import 'react-datepicker/dist/react-datepicker.css'
import { Form } from 'react-bootstrap'
import "./form-field.styles.scss"
/**
 * 
 * @param {groupIcon + action} corresponds to Simple Line icons
 * @param {fontIcon + action} corresponds to Font awesome icons
 * @returns 
 */
export const ATextField = React.forwardRef(({ label, groupicon, groupiconaction, fonticon, fonticonaction, ...props }, ref) => {
  const [field, meta] = useField(props)
  const { children } = label
  const fieldName = field.name
  const { handlechange, ...restProps } = props
  return (
    <div className="form-group">
      <label htmlFor={fieldName}>{ !!children ? children : label}</label>
      {
        (!!groupicon || !!fonticon )? 
        <Field {...field}>
             {({
               field, // { name, value, onChange, onBlur }
               form: { touched, errors }, // also values, setXXXX, handleXXXX, dirty, isValid, status, etc.
               meta,
             }) => (
            <div className="input-group mb-3">          
              <input
                className={`form-control shadow-none ${meta.touched && meta.error && 'is-invalid'}`}
                {...field} {...restProps} ref={ref}
                autoComplete="off"
              />
            
              <span className="input-group-text no-border" onClick={groupiconaction} >
                {
                  !!fonticon ? <FontAwesomeIcon icon={fonticon} /> :  <i className={groupicon}></i>
                }
               
              </span>                                       
            </div> 
            )}
        </Field>
          :
        <Field {...field}>
          {({
            field, // { name, value, onChange, onBlur }
            form: { touched, errors,setFieldValue }, // also values, setXXXX, handleXXXX, dirty, isValid, status, etc.
            meta,
          }) => (
          <input className={`form-control shadow-none ${meta.touched && meta.error && 'is-invalid'}`}
            {...field} {...restProps} autoComplete="off"             
            ref={ref}
            onChange = { e => {
                const domain = e.target.value
                if(!!handlechange) handlechange(domain)
                setFieldValue(fieldName, domain)                
              }
            }
            />
          )}
        </Field>

      }
      

      <ErrorMessage component="div" name={fieldName} className="error" />
    </div>
  )
})

export const ATextArea = ({ label, ...props }) => {
  const [field, meta] = useField(props)
  return (
    <div className="mb-2">
      <label htmlFor={field.name}>{label}</label>
      <textarea
        className={`form-control shadow-none ${meta.touched && meta.error && 'is-invalid'}`}
        {...field} {...props}
        autoComplete="off"
      />
      <ErrorMessage component="div" name={field.name} className="error" />
    </div>
  )
}

export const ASelect = (props) => {

  const { label, name,  options, doChanged, groupelement, ...rest } = props    
  const [field, meta] = useField(props)
  return (
    <div className="mb-2">
      
      <span>
        <label htmlFor={name}>{label}</label>      
        {!!groupelement ? groupelement: null}
      </span>

      <Field as="select" 
          className={`form-control shadow-none ${meta.touched && meta.error && 'is-invalid'}`}
          id={name} name={name} {...field} {...rest} 
          onChange={event => {
              field.onChange(field.name)(event)
              if (!!doChanged) {doChanged(event)}
            }
          }
          >
        { options.map( (option, index) => {
            return (
              <option key={option.key} value={option.value} >
                {option.key}
              </option>
            )
        }

        )}
      </Field>

      {/* <select {...field} {...props} 
      className={`form-control shadow-none ${meta.touched && meta.error && 'is-invalid'}`}
      /> */}
      {meta.touched && meta.error ? (
        <ErrorMessage component="div" name={field.name} className="error" />        
      ) : null}
    </div>
  )

}

export const RadioButtons = props => {
  const { label, name, options, doChanged, ...rest} = props
  const { children } = label
  const type = "radio"
  const [field, meta] = useField(props)
  const outerField = field
    // console.log('rest: ', rest)
  return (
    <>
      <label className="radio-custom-label">{ !!children ? children : label}</label> 
      <div key={`inline-${type}`} className="mb-3">
        <Field name={name} {...rest}
          id={name} 
          className={`form-control shadow-none ${meta.touched && meta.error && 'is-invalid'}`}
          {...field}
        >
            { ({ field }) => {
              const localField = field
              return options.map ( (option, index) => {
                  // console.log('field: ', field.value, ' option: ', option.value)
                    return <Form.Check 
                                key={`default-${type}-${index}`}
                                label={ !!option.highlight ? <span className={`${option.highlight}`}>{option.key}</span> : option.key }
                                {...localField}
                                {...rest}
                                type={type}  
                                value={option.value} 
                                checked={parseInt(localField.value) === option.value}         
                                onChange={event => {
                                  localField.onChange(localField.name)(event)
                                  if (!!doChanged) {doChanged(event)}
                                }
                              }                  
                              />                    
                })
              }
            }
        </Field>
        {meta.touched && meta.error ? (
          <ErrorMessage component="div" name={field.name} className="error" />        
        ) : null}
      </div> 
    </>
  )
}

export const CheckboxGroup = props => {
  const { label, name, options, ...rest} = props
  const [field, meta] = useField(props)
  const type = "checkbox"
  return (
    <>
      <label className="radio-custom-label">{label}</label> 
      <div key={`inline-${type}`} className="mb-3">
        <Field name={name} {...rest}
                  className={`form-control shadow-none ${meta.touched && meta.error && 'is-invalid'}`}
                  {...field}
        >
            { ({ field }) => {
              // console.log(field)
                return options.map ( (option, index) => {
                    
                    return <Form.Check 
                                key={`default-${type}-${index}`}
                                inline
                                label={option.key}
                                {...field}
                                type={type}  
                                value={option.value}      
                                checked={!!field.value ? field.value.includes(`${option.value}`): false}                                               
                              />                    
                })
              }
            }
        </Field>
      </div> 
      <ErrorMessage component="div" name={name} className="error" />                
    </>
  )
}

export const AOptionbox = ({ children, ...props }) => {

  // React treats radios and checkbox inputs differently other input types, select, and textarea.
  // Formik does this too! When you specify `type` to useField(), it will
  // return the correct bag of props for you -- a `checked` prop will be included
  // in `field` alongside `name`, `value`, `onChange`, and `onBlur`

  const [field, meta] = useField({ ...props, type: 'radio' });
  return (

    <>

      <label className="radio-custom-label">
        <input type="radio" {...field} {...props} />
        {children}
      </label>
      {meta.touched && meta.error ? (
        <ErrorMessage component="div" name={field.name} className="error" />                
      ) : null}
    </>
  )
}

export const ADatePickerV2 = ({isTimePicker = false, ...props}) => {
  const {label, name, placeholder, dateFormat, saveDateFormat, ...rest} = props 
  const [ field, meta ] = useField(props)
  
  const [startDate, setStartDate] = useState(new Date());
  const InputGroupComponent = forwardRef(({ value, onClick }, ref) => {    
    // console.log(`date is ${typeof(value)} ${dateFormat}`, moment(value).format(dateFormat))
    let m = moment(value)
    let displayValue = m.isValid() ? m.format(dateFormat) : ''
    return (
    <div className="input-group mb-3">
      <input name={name} type="text" className="form-control" 
          value={displayValue} onClick={onClick} placeholder={placeholder}
          autoComplete="off"
          onChange={(event) => { return }  } 
          />
      <div className="input-group-append">
        <button type="button" className="input-group-text no-border" onClick={onClick} ref={ref}>
          <i className={`${isTimePicker ? 'icon-clock' : 'icon-calendar'}`}></i>
        </button>                       
      </div>                      
    </div>
  )})

  return <>
    <label htmlFor={name}>{label}</label>
    <Field name={name}
                  className={`form-control shadow-none ${meta.touched && meta.error && 'is-invalid'}`}
                  id={name}
                  {...field}
    >{
      ({form}) =>{
        const { setFieldValue, errors, touched } = form
        // console.log('start date ', startDate, 'value = ', field)
        return (
          <div>          
            <DatePicker id={name} 
              {...field}
              {...rest}
              selected={startDate}
              onChange={ val => {
                  let targetDateFormat = saveDateFormat ?? dateFormat
                  const fmtDate = moment(val).format(targetDateFormat)
                  // setStartDate(val)
                  // console.log('date was ', fmtDate)
                  setFieldValue(name, fmtDate)
                }
              }              
              wrapperClassName="date-picker-wrapper"
              customInput={<InputGroupComponent />}
                            
              // showPreviousMonths
              // showYearDropdown
            />
            
          </div>
        )
      }
    }
    </Field>    
    {meta.touched && meta.error ? (
          <ErrorMessage component="div" name={field.name} className="error" />        
        ) : null}
  </>
}

export const ADatePickerV3 = ({isTimePicker = false, ...props}) => {
  const {label, name, placeholder, dateFormat, saveDateFormat, initialData, ...rest} = props 
  const [ field, meta ] = useField(props)
  
  const [startDate, setStartDate] = useState(initialData ?? '');
  const InputGroupComponent = forwardRef(({ value, onClick }, ref) => {    
    // console.log(`date is ${typeof(value)} ${dateFormat}`, moment(value).format(dateFormat))
    return (
    <div className="input-group mb-3">
      <input name={name} type="text" className="form-control" 
          value={value} onClick={onClick} placeholder={placeholder}
          autoComplete="off"
          onChange={(event) => { return }  } 
          />
      <div className="input-group-append">
        <button type="button" className="input-group-text no-border" onClick={onClick} ref={ref}>
          <i className={`${isTimePicker ? 'icon-clock' : 'icon-calendar'}`}></i>
        </button>                       
      </div>                      
    </div>
  )})

  return <>
    <label htmlFor={name}>{label}</label>
    <Field name={name}
                  className={`form-control shadow-none ${meta.touched && meta.error && 'is-invalid'}`}
                  id={name}
                  {...field}
    >{
      ({form}) =>{
        const { setFieldValue, errors, touched } = form
        // console.log('start date ', startDate, 'value = ', field)
        return (
          <div>          
            <DatePicker id={name} 
              {...field}
              {...rest}
              selected={startDate}
              dateFormat={dateFormat}
              onChange={ val => {
                let m = moment(val, dateFormat)
                const fmtDate = m.format(saveDateFormat)
                setFieldValue(name, fmtDate)
                setStartDate(val)
                // console.log(`${fmtDate} ${val}}`)
                }
              }              
              wrapperClassName="date-picker-wrapper"
              customInput={<InputGroupComponent />}
                            
              // showPreviousMonths
              // showYearDropdown
            />
            
          </div>
        )
      }
    }
    </Field>    
    {meta.touched && meta.error ? (
          <ErrorMessage component="div" name={field.name} className="error" />        
        ) : null}
  </>
}

export const ADatePicker = (props) => {
  const {label, name, dateFormat, saveDateFormat, ...rest} = props 
  const [ field, meta ] = useField(props)
  const [startDate, setStartDate] = useState('');

  return <>
    <label htmlFor={name}>{label}</label>
    <Field name={name}>{
      ({form}) =>{
        const { setFieldValue, errors, touched } = form
        // const { value } = field
        // console.log(errors[name], touched[name])
        
        return (
          <div>          
            <DatePicker id={name} 
              {...field}
              {...rest}
              className={`form-control shadow-none ${meta.touched && meta.error && 'is-invalid'}`}
              dateFormat={dateFormat}
              selected={startDate}
              onChange={ val => {
                let m = moment(val, dateFormat)
                const fmtDate = m.format(saveDateFormat)
                setFieldValue(name, fmtDate)
                setStartDate(val)
              }}
              showPreviousMonths
              showYearDropdown
              wrapperClassName="date-picker-wrapper"
            />
            {touched[name] && errors[name] ? (
              <ErrorMessage component="div" name={field.name} className="error" />                
            ) : null}
          </div>
        )
      }
    }
    </Field>    
  </>
}
  

