// 自动配药
import React from 'react';
import { Prompt } from 'react-router-dom';
import {Row, Col, Checkbox, Card, Form, Input, Button, Tabs, Statistic, message, List, Table, Select } from 'antd';
import store from 'store';
import { $http } from 'containers/config/https';
import './style/outpha.less';
import { $PrintPresc,$PrintLabel, $PrintPYD } from './common/Print';
import ColumnAuthoritysModel from 'pages/columnAuthority/ColumnAuthoritysModel';

const Countdown = Statistic.Countdown;
const { Option } = Select;
const TabPane = Tabs.TabPane;
let autoamticTimer = null;

class AutomaticDispensing extends React.Component {

    constructor(props) {
        super(props);
        var userData = JSON.parse(sessionStorage.getItem('userData'));
        this.state = {
            userData,
            buttonStatus: 'start',
            bulletincdStatus: 'start',
            windowDomData: [], // 获取取配药窗口
            parameterSetting: {}, // 取药房参数设置
            checkObj: {}, // 选中窗口的单条数据
            notPrintTotal: 0, // 未打印条数
            havePrintTotal: 0, // 已打印条数
            notPrintData: [], // 未打印
            havePrintData: [], // 已打印
            isPrompt: true,
            selectedRowKeys: [], // 选中行key
            selectedRows: [], // 选中行数据
            numType: 'dispensingNum',
            patNum: undefined,
            activeKey: '1',
            columns: [],
            widthTotal: 0
        };
        this.reprintColumns = [
            {
                title: '病人登记号',
                dataIndex: 'patNo',
                width: '100px',
                align: "center",
            },
            {
                title: '病人性名',
                dataIndex: 'patName',
                width: '100px',
                align: "center",
            },
            {
                title: '处方号',
                dataIndex: 'ordPrescNo',
                width: '100px',
                align: "center",
            },
            {
                title: '配药单号',
                dataIndex: 'pydNo',
                width: '150px',
                align: "center",
            },
        ]
    }

    componentDidMount() {
        this.getDispensingWindow();
        this.getParameterSetting();
        this.getMainTableColumns();
        // 当窗口发生改变的时候
        window.addEventListener('beforeunload', this.beforeunload);
    }

    componentWillUnmount() {
        // 组件销毁前将静止让setState修改state的状态
        clearInterval(autoamticTimer);
        this.setState = (state,callback)=>{ return; }
        window.removeEventListener('beforeunload', this.beforeunload);
    }
    
    // 获取数据列表columns
    getMainTableColumns = () => {
        let {userData} = this.state;
        let data = {
			params: [{
                compontName: "AutomaticDispensing",
                reactCode: ['AutomaticDispensing'],
                type: 'C',
            }]
		}
		$http.post('urlS', this, {
			code: '01040073',
			data: data,
			success: function (res) {
                if (+res.errorCode === 0) {
                    let arr = res.result.C&&res.result.C.length > 0 ? JSON.parse(JSON.stringify(res.result.C)).map((item, index) => {
                        return  {
                            ...item,
                            key: index + 1,
                            title: <div onDoubleClick={() => this.mainColumnRef.onOpenModel()}>{userData.language == 'EN' ? (item&&item.enDescripts ? item.enDescripts : item.title) : item.title}</div>
                        }
                    }) : '';
                    let filterArr = arr.filter(function(item){ return item.display === 'Y'});
                    this.setState({
                        columns: filterArr, widthTotal: res.totalWidth,
                        localeProvider: userData.language == 'EN' ? res.result.language.EN : res.result.language.CN
                    })
                }
			}
		})
    }

    onMainColumnRef = (ref) => {
        this.mainColumnRef = ref;
    }

	//国际化
	setMessage = (name, message, defaultTitle) => {
		return this.state.localeProvider&&this.state.localeProvider[name] ? this.state.localeProvider[name][message] : defaultTitle
	}

    beforeunload = (event) => {
        if(this.state.buttonStatus !== 'start') {
            //用户点击浏览器右上角关闭按钮或是按alt+F4关闭   
            if(event.clientX>document.body.clientWidth&&event.clientY<0||event.altKey)     
            {
                let confirmationMessage = this.setMessage("AutomaticDispensingrefreshPageTips", "descripts", '离开本页面自动配药将会停止! 是否要离开?');
                (event || window.event).returnValue = confirmationMessage;
                return confirmationMessage;
            }   
            //用户点击任务栏，右键关闭。s或是按alt+F4关闭   
            else if(event.clientY > document.body.clientHeight || event.altKey)   
            {   
                let confirmationMessage = this.setMessage("AutomaticDispensingrefreshPageTips", "descripts", '离开本页面自动配药将会停止! 是否要离开?');
                (event || window.event).returnValue = confirmationMessage;
                return confirmationMessage;
            }
            //其他情况为刷新     
            else  
            {     
                let confirmationMessage = this.setMessage("AutomaticDispensingreconfigureTips", "descripts", '刷新本页面自动配药将会停止! 是否要离开?');
                (event || window.event).returnValue = confirmationMessage;
                return confirmationMessage; 
            } 
        }
    }

    // 获取取配药窗口
    getDispensingWindow = () => {
        let data = {
            params: []
        }
        $http.post('urlS', this, {
            code: "02030029",
            data: data,
            success: function (res) {
                if (+res.errorCode === 0) {
                    let arr = res.result[0] && res.result[0].rows && res.result[0].rows.map((item, index) => {
                        return {
                            key: index + 1,
                            checked: false,
                            disabled: false,
                            prepWinDesc: item.prepWinDesc,
                            prepWinID: item.prepWinID,
                            prescNum: item.prescNum
                        }
                    })
                    this.setState({windowDomData: arr}, () => {
                        if(this.state.windowDomData&&this.state.windowDomData.length === 1) {
                            this.compileChecked(this.state.windowDomData[0], 0)
                        }
                    })
                }
            }
        })
    }

    // 3.2.1.4.2.取药房参数设置
    getParameterSetting = () => {
        let data = {
            params: []
        }
        $http.post('urlS', this, {
            code: "02030030",
            data: data,
            success: function (res) {
                if (+res.errorCode === 0) {
                    this.setState({parameterSetting: res.result ? res.result[0] : {}})
                }
            }
        })
    }

    // 调用自动配药信息接口
    automaticDispensingPort = () => {
        let data = {
            params: [
                {
                    prepWinID: this.state.checkObj ? this.state.checkObj.prepWinID : ''
                }
            ]
        }
        $http.post('urlS', this, {
            code: "02030031",
            data: data,
            success: function (res) {
                if (+res.errorCode === 0) {
                    // let arr = [
                    //     {
                    //         patID:"1",
                    //         patNo:"00000144038",
                    //         patName:"赵光辉",
                    //         preDispNo:"PD201906060001",
                    //         dispID:"1",
                    //         ordPrescNo:"O2019060600001",
                    //         ordLocDesc:"急诊科",
                    //     }
                    // ]
                    this.setState({
                        // 讲请求回来的数据和现有的数组结合在一起
                        notPrintData: res.result[0]&&res.result[0].rows ? res.result[0].rows.concat(this.state.notPrintData) : this.state.notPrintData,
                        havePrintTotal: (res.result[0]&&res.result[0].total ? res.result[0].total : 0 ) + this.state.havePrintTotal
                        // notPrintData: arr ? arr.concat(this.state.notPrintData) : this.state.notPrintData,
                        // notPrintTotal: 1 + this.state.notPrintTotal
                    })
                    this.handlePrintPresc(res.result[0]&&res.result[0].rows);
                }
            }
        })
    }

    // 3.2.1.4.3.取自动配药信息
    getAutomaticDispensingInformation = () => {
        let {AutoPrint, RefreshTime} = this.state.parameterSetting;
        if (+AutoPrint === 1) {
            this.automaticDispensingPort();
            let date  = RefreshTime ? RefreshTime * 1000 : null; // 将秒转为毫秒
            // console.log(date)
            autoamticTimer =  setInterval(() => {
                this.automaticDispensingPort();
            }, date);
        }
    }

    // 将状态修改为初始值
    compileStatusStart() {
        this.setState({
            buttonStatus: 'start',
            bulletincdStatus: 'start',
            notPrintTotal: 0,
            havePrintTotal: 0,
            notPrintData: [],
            havePrintData: [],
            checkObj: {},
            activeKey: '1'
        }, () => {
            this.getDispensingWindow()
        })
        clearInterval(autoamticTimer);
    }

    // 开始
    handleStart = () => {
        let messageTrue = true
        if (this.state.windowDomData&&this.state.windowDomData.length > 0) {
            for (let i = 0; i < this.state.windowDomData.length; i++) {
                if (this.state.windowDomData[i].checked == true) {
                    messageTrue = true
                    break;
                } else {
                    messageTrue = false
                }
            }
        }
        if (messageTrue) {
            this.setState({buttonStatus: 'over'}, () => {
                this.getAutomaticDispensingInformation()
            })
        } else if (messageTrue === false) {
            message.error(this.setMessage("AutomaticDispensingpleaseSelectDispensingWin", "descripts", "请选择配药窗口"))
        }
    }

    // 结束
    handleOver = () => {
        if (this.state.bulletincdStatus === 'start') {
            this.setState({bulletincdStatus: 'over'})
        } else {
            this.compileStatusStart()
        }
    }

    // 切换Tabs的回调
    callback = (key) => {
        if (this.state.buttonStatus === 'start') {
            message.info(this.setMessage("AutomaticDispensingnotSupportedRepring", "descripts", "暂不支持重打操作"));
            return
        }
        this.setState({activeKey: key}, () => {
            if (this.state.activeKey==='2') {
                this.handleQueryReprintData();
            }
        })
    }

    // 倒计完成的回调
    onFinish = () => {
        if(this.state.bulletincdStatus === 'over') {
            this.compileStatusStart()
        }
    }

    // Checkbox的onChange事件
    compileChecked = (item, index) => {
        let windowDomData = [...this.state.windowDomData];
        for(var i = 0; i < windowDomData.length; i++) {
            let indexChecked = windowDomData[index].checked;
            windowDomData[i].checked = false;
            windowDomData[index].checked = indexChecked;
            if (windowDomData[i] === item) {
                windowDomData[i].checked = !windowDomData[i].checked;
            }
        }
        this.setState({windowDomData: windowDomData, checkObj: item})
    }

    handleOk = () => {
        this.setState({isPrompt: true}, () => {
            // 跳转到点击切换的路由
            // this.props.dispatch(routerRedux.goBack())
        })
    }

    //打印处方 
    handlePrintPresc = (notPrintData) => {
        let {parameterSetting} = this.state;
        if (!(notPrintData&&notPrintData.length > 0)) {
            return;
        }
        for (let i = 0; i < notPrintData.length; i++) {
            let params = {
                dispID:notPrintData[i].dispID,
                prescno:notPrintData[i].ordPrescNo,
                phFlag:1,
            }
            if (parameterSetting.PrintLabel === '1') {
                $PrintLabel(params);
            }
            if (parameterSetting.PrintPYD === '1') {
                $PrintPYD(params);
            }
            if (parameterSetting.PrintPresc === '1') {
                $PrintPresc(params);
            }
        }
    }

    // 查询输入类型
    handleNumType = e => {
        this.setState({numType: e})
    }

    // 查询病人好
    handlePatNum = e => {
        this.setState({patNum: e.target.value})
    }

    // 查询重打数据
    handleQueryReprintData = () => {
        let data = {
            params: [
                {
                    prepWinID: this.state.checkObj ? this.state.checkObj.prepWinID : '',
                    typeCode: this.state.numType ? this.state.numType : '',
                    number: this.state.patNum ? this.state.patNum : '',
                }
            ]
        }
        $http.post('urlS', this, {
            code: "02030063",
            data: data,
            success: function (res) {
                if (+res.errorCode === 0) {
                    let arr = res.result[0]&&res.result[0].rows ? res.result[0].rows : [];
                    for(var i = 0; i < arr.length; i++) {
                        arr[i].key = i
                    }
                    this.setState({
                        reprintListData: arr,
                        selectedRowKeys:[],
                        selectedRows:[],
                    })
                }
            }
        })
    }

    // 重打
    handleReprint = () => {
        let {parameterSetting} = this.state;
        this.state.selectedRows&&JSON.parse(JSON.stringify(this.state.selectedRows)).map(item => {
            let params = {
                dispID:item.dispID,
                prescno:item.ordPrescNo,
                phFlag:1,
            }
            if (parameterSetting.PrintLabel === '1') {
                $PrintLabel(params);
            }
            if (parameterSetting.PrintPYD === '1') {
                $PrintPYD(params);
            }
            if (parameterSetting.PrintPresc === '1') {
                $PrintPresc(params);
            }
		})
    }

    render() {
        const { getFieldDecorator } = this.props.form;
        let {buttonStatus, bulletincdStatus, windowDomData, parameterSetting, notPrintData, havePrintData, notPrintTotal, havePrintTotal, isPrompt, reprintListData,
            selectedRowKeys, selectedRows, numType, patNum, activeKey, columns, widthTotal, checkObj
        } = this.state;
        const rowSelection = {
            selectedRowKeys,
            selectedRows,
            onChange: (selectedRowKeys, selectedRows) => {
              this.setState({selectedRowKeys, selectedRows})
            }
        };
        let deadline = Date.now() + 1000 * 3;
        let windowDom = (
            windowDomData&&windowDomData.map((item, index) => {
                return (
                    <div key={index} className="check-box" style={{margin: '20px 20px 0 0'}}>
                        <div className="prep-win-desc" style={{background: item.checked ? '#1890FF' : '#69C0FF'}}>{item.prepWinDesc}</div>
                        <div className="presc-num" style={{color: item.checked ? '#1890FF' : '#69C0FF'}}>{item.prescNum}</div>
                        <span>
                            <Checkbox checked={item.checked} onChange={() => this.compileChecked(item, index)} disabled={item.disabled} />
                        </span>
                    </div>
                )
            })
        )
        return (
            <Form className="automatic-dispensing">
                <Row>
                    <Col span={14}>
                        <Card
                            size="small"
                            title={<div className="card-title-left-icon"><div></div>{this.setMessage("AutomaticDispensingdispensingOper", "descripts", "配药操作")}</div>}
                        >
                            <div style={{height: store.getState().tableHeight.y + 204 + 'px', overflow: 'auto'}}>
                                <div style={{display: buttonStatus === 'start' ? 'block' : 'none'}} className="form-dispensing-window">
                                    <Form.Item label={this.setMessage("AutomaticDispensingpleaseSelectDispensingWin", "descripts", "请选择配药窗口：")}>
                                        {getFieldDecorator('window', {
                                            rules: [{ required: true }],
                                        })(
                                            <Row className="ad-window" style={{padding: '0 30px 10px 30px'}}>
                                                {windowDom}
                                            </Row>
                                        )}
                                    </Form.Item>
                                    <Form.Item label={this.setMessage("AutomaticDispensingenterTimeInterval", "descripts", "请输入配药单打印间隔(秒)")}>
                                        {getFieldDecorator('interval', {
                                            initialValue: parameterSetting.RefreshTime ? parameterSetting.RefreshTime : 0,
                                            // rules: [{  required: true, pattern: /^[0-9]\d*$/, message: '只能输入正整数，如0、1、2、3、4' }],
                                        })(
                                            <Input type="number" className="input-number" style={{width: '200px', display: 'block', margin: '20px 30px 10px 30px'}} disabled />,
                                        )}
                                    </Form.Item>
                                </div>
                                <div style={{display: buttonStatus !== 'start' ? 'block' : 'none',}}>
                                    <div style={{fontSize: '14px', height: '36px', lineHeight: '36px', background:' #F7F7F7', paddingLeft: '20px'}}>{this.setMessage("AutomaticDispensingpringTipsHead", "descripts", "正在为")}<span style={{color: '#1999db', fontSize: "16px", margin: "0 6px"}}>{checkObj&&checkObj.prepWinDesc ? checkObj.prepWinDesc : "1号"}</span>{this.setMessage("AutomaticDispensingpringTipsBody", "descripts", "窗口自动打印配药单，时间间隔为：")}<span style={{fontSize: '18px'}}>{parameterSetting.RefreshTime ? parameterSetting.RefreshTime : ''}</span>s。</div>
                                    <div style={{padding: ' 20px 0 0 30px', borderBottom: '1px solid #E1E1E1'}}>
                                        <div style={{marginBottom: '20px', display: bulletincdStatus === 'start' ? 'block' : 'none'}}>
                                            <div style={{width: '100px', marginRight: '20px', display: 'inline-block', textAlign: 'center'}}>
                                                <div style={{height: '32px', lineHeight: '32px', background: '#E1E1E1'}}>{this.setMessage("AutomaticDispensingprinted", "descripts", "已打印")}</div>
                                                <div style={{height: '36px', lineHeight: '36px', fontSize: '18px', border: '1px solid #E1E1E1'}}>{havePrintTotal}</div>
                                            </div>
                                            {/* <div style={{width: '100px', display: 'inline-block', textAlign: 'center'}}>
                                                <div style={{height: '32px', lineHeight: '32px', background: '#E1E1E1'}}>{this.setMessage("AutomaticDispensingnotPrint", "descripts", "未打印")}</div>
                                                <div style={{height: '36px', lineHeight: '36px', fontSize: '18px', color: '#1999db', border: '1px solid #E1E1E1'}}>{notPrintTotal}</div>
                                            </div> */}
                                            {/* <h2 style={{color: 'red', fontSize: '20px'}}>目前已有<span> 10 </span>种药品库存不足，配药时请注意!</h2> */}
                                        </div>
                                        <div style={{marginBottom: '36px', display: bulletincdStatus !== 'start' ? 'block' : 'none'}}>
                                            <div>
                                                <div style={{color: 'red', fontSize: '14px'}}>{this.setMessage("AutomaticDispensingprintingTips", "descripts", "正在打印队列中剩余的配药单，请勿关闭窗口。")}</div>
                                                <div style={{color: '#999'}}>{this.setMessage("AutomaticDispensingdispensingForm", "descripts", "配药单：")}<Countdown style={{display: 'inline-block', color: 'red'}} value={deadline} format="ss" onFinish={this.onFinish} /></div>
                                            </div>
                                        </div>
                                    </div>
                                </div>
                                <Row style={{padding: '20px 30px 0'}}>
                                    <Button type="primary" style={{width: '100px', marginRight: '16px'}} onClick={this.handleStart} disabled={buttonStatus !== 'start'}>{this.setMessage("AutomaticDispensingstart", "descripts", "开始")}</Button>
                                    <Button style={{width: '100px'}} onClick={this.handleOver} disabled={buttonStatus === 'start'}>{this.setMessage("AutomaticDispensingend", "descripts", "结束")}</Button>
                                    <Row style={{color: 'rgba(0, 0, 0, 0.4)', marginTop: '8px', display: buttonStatus !== 'start' ? 'block' : 'none'}}>{this.setMessage("AutomaticDispensingreconfigureTips", "descripts", "如需重新配置窗口请先点击结束")}</Row>
                                </Row>
                            </div>
                        </Card>
                    </Col>
                    <Col span={10}>
                        <div style={{paddingLeft: '6px', position: 'relative'}}>
                            <Card
                                size="small"
                                title={<div className="card-title-left-icon"><div></div>{this.setMessage("AutomaticDispensingprintState", "descripts", "打印状况")}</div>}
                                // extra={<a href="#">More</a>}
                                className="card-title-bg"
                            >
                                <div style={{height: store.getState().tableHeight.y + 204 + 'px', overflow: 'auto', padding: '12px'}}>
                                    <Tabs activeKey={activeKey} onChange={this.callback}>
                                        <TabPane tab={this.setMessage("AutomaticDispensingprinted", "descripts", "已打印")} key="1">
                                            <div style={{marginTop: '10px'}}>
                                                <div style={{display: buttonStatus === 'start' ? 'block' : 'none'}}>{this.setMessage("AutomaticDispensinghasNotStarted", "descripts", "未开始")}</div>
                                                <div style={{height: store.getState().tableHeight.y + 76 + 'px', overflow: 'auto', display: buttonStatus !== 'start' ? 'block' : 'none'}}>
                                                    <List
                                                        itemLayout="horizontal"
                                                        dataSource={notPrintData}
                                                        renderItem={(item, index) => (
                                                            <List.Item>
                                                                <div style={{height: '50px', lineHeight: '50px', fontSize: '18px'}}>
                                                                    <span className="circle" style={{marginRight: '25px', background: 'rgb(245, 245, 245)'}}>{index + 1}</span>{item.patName}<span style={{fontSize: '16px', marginLeft: '8px'}}>{item.preDispNo}</span>
                                                                </div>
                                                                <div style={{position: "absolute", right: 0}}>
                                                                    <div><span style={{display: 'inline-block', width: '60px', textAlign: 'right'}}>{this.setMessage("AutomaticDispensingordPrescNo", "descripts", "处方号：")}</span>{item.ordPrescNo}</div>
                                                                    <div><span style={{display: 'inline-block', width: '60px', textAlign: 'right'}}>{this.setMessage("AutomaticDispensingloc", "descripts", "科室：")}</span>{item.ordLocDesc}</div>
                                                                </div>
                                                            </List.Item>
                                                        )}
                                                    />
                                                </div>
                                            </div>
                                        </TabPane>
                                        <TabPane tab={this.setMessage("AutomaticDispensingrePrint", "descripts", "重打")} key="2">
                                            <div>
                                                <div style={{display: buttonStatus === 'start' ? 'block' : 'none'}}>{this.setMessage("AutomaticDispensinghasNotStarted", "descripts", "未开始")}</div>
                                                <div style={{height: store.getState().tableHeight.y + 76 + 'px', overflow: 'auto', display: buttonStatus !== 'start' ? 'block' : 'none'}}>
                                                    <div style={{margin: '10px 0'}}>
                                                        <Select style={{width: '150px'}} value={numType} onChange={this.handleNumType} allowClear>
                                                            <Option value="dispensingNum">{this.setMessage("AutomaticDispensingorderNum", "descripts", "配药单号")}</Option>
                                                            <Option value="prescription">{this.setMessage("AutomaticDispensingordPrescNo", "descripts", "处方号")}</Option>
                                                            <Option value="patNo">{this.setMessage("AutomaticDispensingpatNo", "descripts", "病人ID")}</Option>
                                                            <Option value="patName">{this.setMessage("AutomaticDispensingpatientName", "descripts", "病人姓名")}</Option>
                                                        </Select>
                                                        <Input placeholder={this.setMessage("AutomaticDispensinginputTips", "descripts", "请输入")} style={{width: '150px', margin: '0 8px'}} value={patNum} onChange={this.handlePatNum} />
                                                        <Button onClick={this.handleQueryReprintData}>{this.setMessage("AutomaticDispensingsearch", "descripts", "查询")}</Button>
                                                        <Button onClick={this.handleReprint} type="dashed" style={{marginLeft: '30px'}}>{this.setMessage("AutomaticDispensingrePrint", "descripts", "重打")}</Button>
                                                    </div>
                                                    <Table
                                                        dataSource={reprintListData}
                                                        columns={columns&&columns.length > 0 ? columns : this.reprintColumns}
                                                        rowSelection={rowSelection}
                                                        bordered
                                                        pagination={false}
                                                        scroll={{x: columns&&columns.length > 0 ? widthTotal : 450}}
                                                    />
                                                    {/* <CommonPagination size='small' current={this.state.page} total={this.state.total} search= 'search'
                                                      onShowSizeChange={this.onShowSizeChange.bind(this)} complete={true} dataSource={this.state.WaListData}
                                                      loading={this.state.loading} onChange={this.onChange.bind(this)} /> */}
                                                </div>
                                            </div>
                                        </TabPane>
                                    </Tabs>
                                </div>
                            </Card>
                            <div style={{width: '6px', background: 'rgba(240, 242, 245, 1)', position: 'absolute', top: 0, left: 0, height: '100%'}}></div>
                        </div>
                    </Col>
                </Row> 
               {this.state.buttonStatus !== 'start' ? <Prompt 
                message={this.setMessage("AutomaticDispensingleavePageTips", "descripts", "离开本页面自动配药将会停止! 是否要离开?")}
                // message={
                //     () => {
                //         if (!isPrompt) {
                //             return true;
                //         }
                //         Modal.confirm({
                //             title: '离开本页面自动配药将会停止! ',
                //             content: '是否要离开?',
                //             okText: '确认',
                //             cancelText: '取消',
                //             onOk: this.handleOk,
                //             onCancel: () => this.setState({isPrompt: false}),
                //         })
                //         return false;
                //     }
                // } 
               when={isPrompt}/> : ''}
                <ColumnAuthoritysModel
                    clientWidth='800px'
                    compontName='AutomaticDispensing'
                    configType="C"
                    onRef={this.onMainColumnRef}
                    reloadData={this.getMainTableColumns}
                />
            </Form >
        )
    }
};
const AutomaticDispensingForm = Form.create()(AutomaticDispensing);
export default AutomaticDispensingForm;