@extends('layout.base')

@section('page_title')
Editar Propietario
@endsection

@section('page_content')
<div class="ui container">
    <h2 class="ui header">Editar Propietario</h2>
    <form class="ui form" id="edit_form">
        <input type="hidden" name="venta_id" value="{{$venta_id}}" />
        <div class="two wide field">
            <label for="rut">RUT</label>
            <div class="ui right labeled input" id="rut">
                <input type="text" name="rut" value="{{number_format($propietario->rut, 0, ',', '.')}}" />
                <div class="ui basic label">-<span id="digito">{{$propietario->dv}}</span></div>
            </div>
        </div>
        <div class="fields">
            <div class="field">
                <label for="nombres">Nombre</label>
                <input type="text" name="nombres" id="nombres" value="{{trim($propietario->nombres)}}" />
            </div>
            <div class="field">
                <label for="apellido_paterno">Apellido Paterno</label>
                <input type="text" id="apellido_paterno" name="apellido_paterno" value="{{$propietario->apellidos['paterno']}}" />
            </div>
            <div class="field">
                <label for="apellido_materno">Apellido Materno</label>
                <input type="text" id="apellido_materno" name="apellido_materno" value="{{$propietario->apellidos['materno']}}" />
            </div>
        </div>
        <div class="fields">
            <div class="field">
                <label for="calle">Dirección</label>
                <input type="text" name="calle" id="calle" value="{{$propietario->datos->direccion->calle}}" />
            </div>
            <div class="field">
                <label for="numero">Número</label>
                <input type="number" id="numero" size="6" name="numero" value="{{$propietario->datos->direccion->numero}}" />
            </div>
            <div class="field">
                <label for="extra">Información Adicional*</label>
                <input type="text" id="extra" name="extra" value="{{$propietario->datos->direccion->extra}}" />
            </div>
        </div>
        <div class="fields">
            <div class="field">
                <label for="region">Región</label>
                <select id="region" name="region" class="ui search selection dropdown">
                    @foreach($regiones as $region)
                        <option value="{{$region->id}}"{{($propietario->datos->direccion->comuna->provincia->region->id === $region->id) ? ' selected="selected"' : ''}}>{{$region->numeral}} {{$region->descripcion}}</option>
                    @endforeach
                </select>
            </div>
            <div class="field">
                <label for="comunas">Comuna</label>
                <select class="ui search selection dropdown" name="comuna" id="comunas"></select>
            </div>
        </div>
        <button class="ui button" id="guardar_button">Guardar</button>
    </form>
</div>
@endsection

@push('page_scripts')
<script type="text/javascript">
    class Propietario {
        props
        constructor({rut, digito, nombres, apellidos: {paterno, materno}, direccion: {calle, numero, extra, comuna, region}}) {
            this.props = {
                rut,
                digito,
                nombres,
                apellidos: {
                    paterno,
                    materno
                },
                direccion: {
                    calle,
                    numero,
                    extra,
                    comuna,
                    region
                },
            }
        }

        update() {
            return {
                rut: rut => {
                    this.props.rut = rut
                    this.update().digito(Rut.digito(this.props.rut))
                },
                digito: digito => {
                    this.props.digito = digito
                },
                nombres: nombres => {
                    this.props.nombres = nombres
                },
                apellidos: () => {
                    return {
                        paterno: paterno => {
                            this.props.apellidos.paterno = paterno
                        },
                        materno: materno => {
                            this.props.apellidos.materno = materno
                        }
                    }
                },
                direccion: () => {
                    return {
                        calle: calle => {
                            this.props.direccion.calle = calle
                        },
                        numero: numero => {
                            this.props.direccion.numero = numero
                        },
                        extra: extra => {
                            this.props.direccion.extra = extra
                        },
                        comuna: comuna => {
                            this.props.direccion.comuna = comuna
                        },
                        region: region => {
                            this.props.direccion.region = region
                        }
                    }
                }
            }
        }
        edit() {
            const uri = '{{$urls->api}}/venta/{{$venta_id}}/propietario/edit'
            const originales = {
                rut: '{{trim($propietario->rut)}}',
                nombres: '{{trim($propietario->nombres)}}',
                apellidos: {
                    paterno: '{{trim($propietario->apellidos['paterno'])}}',
                    materno: '{{trim($propietario->apellidos['materno'])}}'
                },
                direccion: {
                    calle: '{{trim($propietario->datos->direccion->calle)}}',
                    numero: '{{$propietario->datos->direccion->numero}}',
                    extra: '{{trim($propietario->datos->direccion->extra)}}',
                    comuna: '{{$propietario->datos->direccion->comuna->id}}'
                }
            }
            const data = {}
            const collator = new Intl.Collator('es')
            Object.entries(originales).forEach(([key, value]) => {
                if (key === 'apellidos') {
                    Object.entries(value).forEach(([k, v]) => {
                        const val = this.props[key][k]
                        if (collator.compare(val, v) !== 0) {
                            data[`apellido_${k}`] = val
                        }
                    })
                    return
                }
                if (key === 'direccion') {
                    let changed = false
                    Object.entries(value).forEach(([k, v]) => {
                        const val = this.props[key][k]
                        if (collator.compare(val, v) !== 0) {
                            changed = true
                            data[k] = val
                        }
                    })
                    if (changed) {
                        Object.entries(value).forEach(([k, v]) => {
                            if (k in data) {
                                return
                            }
                            data[k] = this.props[key][k]
                        })
                    }
                    return
                }
                const val = this.props[key]
                if (collator.compare(val, value) !== 0) {
                    data[key] = val
                }
            })
            if (Object.keys(data).length === 0) {
                // No changes
                propietario.redirect()
                return
            }
            if ('rut' in data) {
                data['dv'] = Rut.digito(data['rut'])
            }
            return fetchAPI(uri,
                {method: 'put', headers: {'Content-Type': 'application/json'}, body: JSON.stringify(data)}
            ).then(response => {
                if (!response) {
                    return
                }
                return response.json().then(data => {
                    if (data.edited) {
                        propietario.redirect()
                    }
                })
            })
        }
    }
    class Region {
        props
        comunas

        constructor({id, descripcion, selected = false}) {
            this.props = {
                id,
                descripcion,
                selected
            }
            this.comunas = []
        }
        get() {
            return {
                comunas: () => {
                    if (this.comunas.length > 0) {
                        return new Promise(resolve => resolve())
                    }
                    const uri = '{{$urls->api}}/direcciones/region/' + this.props.id + '/comunas'
                    return fetchAPI(uri).then(response => {
                        if (!response) {
                            return
                        }
                        return response.json().then(data => {
                            if (data.total === 0) {
                                return
                            }
                            this.comunas = data.comunas.map(comuna => {
                                let selected = false
                                if (comuna.id === {{$propietario->datos->direccion->comuna->id}}) {
                                    selected = true
                                }
                                return {
                                    id: comuna.id,
                                    descripcion: comuna.descripcion,
                                    selected
                                }
                            })
                        })
                    })
                }
            }
        }
    }
    class Form {
        static submit(event) {
            event.preventDefault()
            propietario.props.data.edit()
            return false
        }
    }
    class Watcher {
        static rut() {
            const rut = $("[name='rut']")
            rut.on('input', EventHandler.rut().update)
            rut.on('blur', EventHandler.rut().change)
        }
        static nombres() {
            $("[name='nombres']").change(event => {
                propietario.props.data.update().nombres($(event.currentTarget).val())
            })
        }
        static apellidos() {
            const watched = [
                'apellido_paterno',
                'apellido_materno'
            ]
            watched.forEach(name => {
                $("[name='" + name + "']").change(event => {
                    const value = $(event.currentTarget).val()
                    const key = name.split('_')[1]
                    propietario.props.data.update().apellidos()[key](value)
                })
            })
        }
        static direccion() {
            const watched = [
                'calle',
                'numero',
                'extra'
            ]
            watched.forEach(name => {
                $("[name='" + name + "']").change(EventHandler.direccion)
            })
        }
        static region() {
            $('#region').change(EventHandler.region)
        }
        static comuna() {
            $('#comunas').change(event => {
                const comuna_id = $(event.currentTarget).val()
                propietario.props.data.update().direccion().comuna(comuna_id)
            })
        }

        static run() {
            Watcher.rut()
            Watcher.nombres()
            Watcher.apellidos()
            Watcher.direccion()
            Watcher.region()
            Watcher.comuna()
        }
    }
    class EventHandler {
        static region(event) {
            const region_id = $(event.currentTarget).val()
            propietario.props.regiones.forEach(region => {
                region.props.selected = false
            })
            const region = propietario.props.regiones.find(region => region.props.id === region_id)
            region.props.selected = true
            region.get().comunas().then(() => {
                propietario.draw().comunas()
            })
        }
        static direccion(event) {
            const names = [
                'calle',
                'numero',
                'extra'
            ]
            const originals = [
                '{{trim($propietario->datos->direccion->calle)}}',
                '{{trim($propietario->datos->direccion->numero)}}',
                '{{trim($propietario->datos->direccion->extra)}}'
            ]
            const values = []
            names.forEach(name => {
                const val = $("[name='" + name + "']").val()
                propietario.props.data.update().direccion()[name](val)
                values.push(val)
            })
            const collator = new Intl.Collator('es')
            if (collator.compare(originals.join(' '), values.join(' ')) !== 0) {
                propietario.find().comuna(values.join(' ').trim())
            }
        }
        static rut() {
            return {
                change: event => {
                    const rut = $("[name='rut']").val().replace(/\D/g, '')
                    if (rut.length < 7) {
                        return
                    }
                    propietario.find().propietario(rut)
                },
                update: event => {
                    const input = $("[name='rut']")
                    const rut = input.val().replace(/\D/g, '')
                    propietario.props.data.update().rut(rut)
                    input.val(Rut.format(rut))
                    $('#digito').html(propietario.props.data.props.digito)
                }
            }
        }
    }
    class Rut {
        static format(rut) {
            return Intl.NumberFormat('es-CL', {maximumFractionDigits: 0}).format(rut)
        }
        static digito(rut) {
            const cleanRut = rut.replace(/\D/g, ''); // Removes non-digit characters more efficiently
            let sum = 0;
            const factors = [2, 3, 4, 5, 6, 7, 2, 3, 4, 5];
            for (let i = 0; i < cleanRut.length; i++) {
                const digit = parseInt(cleanRut[cleanRut.length - 1 - i], 10);
                sum += digit * factors[i % factors.length];
            }
            const dv = 11 - (sum % 11);
            return dv === 10 ? 'K' : dv === 11 ? '0' : dv.toString();
        }
    }
    const propietario = {
        props: {
            ids: {},
            data: {},
            regiones: [],
        },
        update() {
            return {
                propietario: () => {
                    $("[name='rut']").val(Rut.format(this.props.data.props.rut))
                    $('#digito').html(this.props.data.props.digito)
                    $("[name='nombres']").val(this.props.data.props.nombres)
                    $("[name='apellido_paterno']").val(this.props.data.props.apellidos.paterno)
                    $("[name='apellido_materno']").val(this.props.data.props.apellidos.materno)
                    $("[name='calle']").val(this.props.data.props.direccion.calle)
                    $("[name='numero']").val(this.props.data.props.direccion.numero)
                    $("[name='extra']").val(this.props.data.props.direccion.extra)
                    $('#region').val(this.props.data.props.direccion.region)
                    this.update().region()
                },
                region: () => {
                    this.props.regiones.forEach(region => {
                        region.props.selected = false
                    })
                    this.props.regiones.filter(region => region.props.id === this.props.data.props.direccion.region).forEach(region => {
                        region.props.selected = true
                    })
                    const promises = []
                    this.props.regiones.filter(region => region.props.selected).forEach(region => {
                        promises.push(region.get().comunas())
                    })
                    Promise.all(promises).then(() => {
                        this.draw().comunas()
                    })
                }
            }
        },
        find() {
            return {
                propietario: rut => {
                    const uri = '{{$urls->api}}/ventas/propietario/' + rut
                    return fetchAPI(uri).then(response => {
                        if (!response) {
                            this.draw().reset()
                            return
                        }
                        return response.json().then(data => {
                            if (data.propietario === null) {
                                this.draw().reset()
                                return
                            }
                            this.props.data.update().nombres(data.propietario.nombres)
                            this.props.data.update().apellidos().paterno(data.propietario.apellidos.paterno)
                            this.props.data.update().apellidos().materno(data.propietario.apellidos.materno)
                            this.props.data.update().direccion().calle(data.propietario.direccion.calle)
                            this.props.data.update().direccion().numero(data.propietario.direccion.numero)
                            this.props.data.update().direccion().extra(data.propietario.direccion.extra)
                            this.props.data.update().direccion().comuna(data.propietario.direccion.comuna.id)
                            this.props.data.update().direccion().region(data.propietario.direccion.comuna.provincia.region.id)
                            this.update().propietario()
                        })
                    })
                },
                comuna: direccion => {
                    const original_id = $("[name='comuna']").val()
                    const uri = '{{$urls->api}}/direcciones/comunas/find'
                    const data = {direccion}
                    return fetchAPI(uri,
                        {method: 'post', headers: {'Content-Type': 'application/json'}, body: JSON.stringify(data)}
                    ).then(response => {
                        if (!response) {
                            return
                        }
                        return response.json().then(data => {
                            if (data.total === 0) {
                                return
                            }
                            const comuna_id = data.comunas[0].id
                            if (comuna_id === original_id) {
                                return
                            }
                            const parent = $('#comunas')
                            parent.dropdown('set selected', comuna_id)
                        })
                    })
                }
            }
        },
        draw() {
            return {
                comunas: () => {
                    const parent = $(this.props.ids.comuna)
                    parent.html('')
                    const region_id = $(this.props.ids.region).val()
                    const comunas = this.props.regiones.find(region => region.props.id === region_id).comunas
                    comunas.forEach(comuna => {
                        const option = $('<option></option>')
                        option.attr('value', comuna.id).html(comuna.descripcion)
                        if (parseInt(comuna.id) === parseInt(this.props.data.props.direccion.comuna)) {
                            option.prop('selected', true)
                        }
                        parent.append(option)
                    })
                    parent.show()
                    parent.dropdown()
                },
                reset: () => {
                    $("[name='nombres']").val('')
                    $("[name='apellido_paterno']").val('')
                    $("[name='apellido_materno']").val('')
                    $("[name='calle']").val('')
                    $("[name='numero']").val('')
                    $("[name='extra']").val('')
                }
            }
        },
        redirect() {
            window.location = '{{$urls->base}}/venta/{{$venta_id}}'
        },
        setup({ids, propietario}) {
            this.props.ids = ids
            this.props.data = propietario

            $(this.props.ids.region).dropdown()
            $(this.props.ids.region).change(EventHandler.region)

            $(this.props.ids.comuna).hide()
            $(this.props.ids.region).find('option').each((index, element) => {
                const id = $(element).val()
                const descripcion = $(element).text()
                const selected = $(element).prop('selected')
                this.props.regiones.push(new Region({id, descripcion, selected}))
            })
            this.update().region()

            $(this.props.ids.forms.edit).submit(Form.submit)
            Watcher.run()
        }
    }

    $(document).ready(() => {
        propietario.setup({
            ids: {
                region: '#region',
                comuna: '#comunas',
                forms: {
                    edit: '#edit_form'
                },
                buttons: {
                    guardar: '#guardar_button'
                }
            },
            propietario: new Propietario({
                rut: '{{$propietario->rut}}',
                digito: '{{$propietario->dv}}',
                nombres: '{{$propietario->nombres}}',
                apellidos: {
                    paterno: '{{$propietario->apellidos['paterno']}}',
                    materno: '{{$propietario->apellidos['materno']}}'
                },
                direccion: {
                    calle: '{{$propietario->datos->direccion->calle}}',
                    numero: '{{$propietario->datos->direccion->numero}}',
                    extra: '{{$propietario->datos->direccion->extra}}',
                    comuna: '{{$propietario->datos->direccion->comuna->id}}',
                    region: '{{$propietario->datos->direccion->comuna->provincia->region->id}}',
                }
            })
        })
    })
</script>
@endpush
