<?php

namespace app\controllers;

use Yii;
use yii\web\Controller;
use yii\web\Response;
use yii\mongodb\Query;
use app\models\Form;
use app\models\FormSearch;
use app\components\Utilities;
use app\components\FormHelpers;
use kartik\rating\StarRating;
use yii\web\UploadedFile;
use yii\web\NotFoundHttpException;

class FormsController extends Controller
{
    // The normal user mustn't execute any action if he/she hasn't selected a node to complete login
    public function beforeAction($action){
        if($action->id != 'public-form' && $action->id != 'get-child-data-from-parent-list'){
            if(! Yii::$app->session->get('user.active_node')){
                return $this->redirect(['/users/login-as'])->send();    // send() is required in beforeAction method
            }
        }
        return parent::beforeAction($action);
    }

    public function behaviors()
    {
        return [
            'access' => [
                'class' => \yii\filters\AccessControl::class,
                'rules' => [
                    [
                        'allow' => true,
                        'actions' => ['get-child-data-from-parent-list'],
                        'roles' => ['?', '@']
                    ],
                    [
                        'allow' => true,
                        'roles' => ['@']
                    ],
                ],
                'denyCallback' => function(){
                    if(Yii::$app->user->isGuest){
                        return Yii::$app->response->redirect(['/users/login']);
                    }
                    return Yii::$app->response->redirect(Yii::$app->homeUrl);
                }
            ],
			// For development cases only
			// Uncomment the following only when you have to update lookup field in form-builder js module
			// 'corsFilter'  => [
			// 	'class' => \yii\filters\Cors::className(),
			// 	'cors'  => [
			// 		'Origin' => ['*'],
			// 	],
			// ],
        ];
    }

    public function actionFormBuilder(){
        // Only Admin can creat new forms
        if(! Yii::$app->user->can('Admin')){
            return $this->redirect(['index']);
        }
        
        return $this->render('form-builder');
    }

    public function actionIndex(){
        $searchModel = new FormSearch();
        $dataProvider = $searchModel->search(Yii::$app->request->queryParams);

        $forms_permissions = null;
        if(! Yii::$app->user->can('Admin')){
            $forms_permissions = Utilities::getUserPermissions();
        }

        return $this->render('index', [
            'searchModel' => $searchModel,
            'dataProvider' => $dataProvider,
            'forms_permissions' => $forms_permissions
        ]);
    }

    public function actionSaveForm(){
        Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
        $data = Yii::$app->request->post();
        $fields         = json_decode($data['formData'], true);
        $form_name      = $data['form_name'];
        $directionality = $data['form_direction'];  // The directionality of rendering form fields
        $type           = $data['form_type'];       // The type of form (restricted or global)

        $collection = Yii::$app->mongodb->getCollection('forms');
        $formId = $collection->insert([
            'name' => $form_name,
            'createdAt' => Utilities::getDateTime(),
            'directionality' => $directionality,
            'type' => $type,
            'status' => 'Active',
        ]);

        if($formId){
            // Check if form contains Lookup field
            Utilities::checkForLookupFieldAndInsertItToLookupCollections($formId, $fields);

            $collection = Yii::$app->mongodb->getCollection('formsVersions');
            $result = $collection->insert([
                'formId'        => Utilities::getIdAsObject($formId),
                'createdAt'     => Utilities::getDateTime(),
                'versionNumber' => 1,
                'status'        => 'Active',
                'fields'        => $fields
            ]);

            if($result){
                // Save columns in formsAndViewsNeededColumns collection
                $this->saveFormColumnsForDataTable($formId, $fields);

                Yii::$app->session->setFlash('form_saved', Yii::t('app', 'The form has been saved successfully'));
                return json_encode(['status' => true]);
            }
        }
        return json_encode(['status' => false]);
    }

    protected function findModel($id){
        if(($model = Form::findOne($id)) != null){
            return $model;
        }

        throw new NotFoundHttpException(Yii::t('app', 'The requested page does not exist.'));
    }

    public function actionRenderForm($id, $view_id = null){
        // The user can only submit the forms in his/her assigned groups
        if(! Yii::$app->user->can('Admin')){
            if(! Utilities::checkPermissionForForm($id, 'submit')){
                return $this->redirect(['index']);
            }
        }

        // Check form status (if it's inactive, the form mustn't be rendered)
        if(! Utilities::formIsActive($id)){
            return $this->redirect(['index']);
        }

        $form_id = $id; // TEMP
        $form = Utilities::getActiveVersionOfForm($form_id);
        $all_fields = FormHelpers::prepareFields($form_id, $form['fields'], $form['versionNumber']);
        $form_fields = $all_fields['form_fields'];
        $other_fields = $all_fields['other_fields'];
        $model = $form_fields[0]::$model;

        if (Yii::$app->request->isAjax) {
            $model->load(Yii::$app->request->post());
            Yii::$app->response->format = Response::FORMAT_JSON;
            return \yii\widgets\ActiveForm::validate($model);
        }

        if(Yii::$app->request->isPost){
            $data = Yii::$app->request->post();
            $model->load($data);
            
            // Must handle files in order to pass validation
            // document_id will be generated finally, so we will keep the filesCollection documents_IDs in array in order to add document_id later
            $saved_files_IDs = Utilities::handleUploadedFilesInSubmission($form_id, $form_fields, $model, $data);

            if($model->validate()){
                
                $dynamic_model_data = null;
                $matrix_data = [];
                FormHelpers::extractSubmittedData($data, $dynamic_model_data, $matrix_data);

                $submitted_data = [];
                FormHelpers::handleSubmittedFields($dynamic_model_data, $submitted_data, $form_id, $form['versionNumber']);
                
                $temp_matrix_data = [];
                FormHelpers::handleSubmittedMatrixFields($matrix_data, $temp_matrix_data);
                
                FormHelpers::handleIDsFields($form_id, $submitted_data);
                
                $saved_document_id = $this->saveSubmittedData($form_id, $form['versionNumber'], $submitted_data);
                if($saved_document_id){
                    Utilities::addDocumentIdToSavedFiles($saved_files_IDs, $saved_document_id);

                    foreach($temp_matrix_data as $matrix_name => $item){
                        $this->saveSubmittedMatrixData($saved_document_id, $matrix_name, $item);
                    }
                }
                $save_and_new = 'save-and-new';
                if(isset($data[$save_and_new])){
                    return $this->redirect(['render-form', 'id' => $form_id]);
                }
                elseif($view_id){
                    return $this->redirect(['views/data', 'id' => $view_id]);        
                }
                return $this->redirect(['view-record', 'form_id' => $form_id, 'document_id' => (string)$saved_document_id]);    
            }
        }
        
        return $this->render('render-form', [
            'form_fields'   => $form_fields,
            'other_fields'  => $other_fields,
            'direction'     => Utilities::getFormDirectionality($form_id),
            'form_id'       => $form_id,
        ]);
    }
    
    public function saveSubmittedData($form_id, $form_version, $data, $update_flag = false, $document_id = null){
        $collection = Yii::$app->mongodb->getCollection('forms_' . $form_id);
        $data_item = [];
        foreach($data as $item){
            if(! Utilities::isMatrix($item['name'])){
                $data_item[$item['name']] = $item['value'];
            }
        }
        if($update_flag){
            $data_item['lastUpdatedBy'] = Yii::$app->user->identity->_id;
            $data_item['lastUpdatedAt'] = Utilities::getDateTime();

            $result = $collection->update([
                '_id' => Utilities::getIdAsObject($document_id)
            ], [
                '$set' => $data_item
            ]);

            // If we return $result, it might be 0 if the user hasn't change any value, so we return document_id
            return $document_id;
        }

        $data_item['submittedBy'] = Yii::$app->user->identity->_id;
        $data_item['submittedAt'] = Utilities::getDateTime();
        $data_item['formVersion'] = $form_version;
        $data_item['ownerNodeId'] = (Yii::$app->user->identity->is_admin ? Utilities::getIdAsObject(Yii::$app->session->get('user.admin_submit_active_node')) : Utilities::getUserActiveNode());
        $result = $collection->insert($data_item);

        if($result){
            // dataNodesCollections is used to facilitate searching of data in collections and owner node
            Utilities::addRecordToDataNodesCollections($data_item['ownerNodeId'], $result, 'forms_' . $form_id);
        }
        return $result;
    }

    public function saveSubmittedMatrixData($parent_document_id, $matrix_name, $data, $update_flag = false, $parent_form_id = null){
        $collection = Yii::$app->mongodb->getCollection($matrix_name);

        // When updating parent record, we can't track changes of matrix records (what has added, what has edited or removed ...)
        // so, we delete all previous records and insert the submitted records again
        // but in order not to loose the necessary data (submittedBy, submittedAt and ownerNodeId) we get it from parent and append it to records 
        if($update_flag){
            $parent_document_user_id = null;
            $parent_document_submission_date = null;
            $owner_node_id = null;

            // Delete all previous documents
            $collection->remove(['id' => Utilities::getIdAsObject($parent_document_id)]);

            // Get needed data from parent document
            $parent_document = Utilities::getSpecificDocument($parent_form_id, $parent_document_id);
            if($parent_document){
                $parent_document_user_id = $parent_document['submittedBy'];
                $parent_document_submission_date = $parent_document['submittedAt'];
                $owner_node_id = $parent_document['ownerNodeId'];
            }
        }

        foreach($data as $record){
            $data_item = [];
            $data_item['id'] = Utilities::getIdAsObject($parent_document_id);
            foreach($record as $key => $value){
                $data_item[$key] = $value;
            }

            if($update_flag){
                $data_item['submittedBy'] = $parent_document_user_id;
                $data_item['submittedAt'] = $parent_document_submission_date;
                $data_item['ownerNodeId'] = $owner_node_id;
                $data_item['lastUpdatedBy']   = Yii::$app->user->identity->_id;
                $data_item['lastUpdatedAt']   = Utilities::getDateTime();
            }
            else{
                $data_item['submittedBy'] = Yii::$app->user->identity->_id;
                $data_item['submittedAt'] = Utilities::getDateTime();
                $data_item['ownerNodeId'] = (Yii::$app->user->identity->is_admin ? Utilities::getIdAsObject(Yii::$app->session->get('user.admin_submit_active_node')) : Utilities::getUserActiveNode());
            }

            $result = $collection->insert($data_item);

            if($result && ! $update_flag){
                // dataNodesCollections is used to facilitate searching of data in collections and owner node
                Utilities::addRecordToDataNodesCollections($data_item['ownerNodeId'], $result, $matrix_name);
            }
        }
    }

    public function actionGetChildDataFromParentList($form_id, $version_number, $name, $value){
        $res = (new Query())
            ->from('formsVersions')
            ->where([
                'formId' => Utilities::getIdAsObject($form_id),
                'versionNumber' => (int)$version_number
            ])
            ->one();

        $items = [];
        if($res){
            foreach($res['fields'] as $field){
                if($field['name'] == $name){
                    foreach($field['values'] as $item){
                        if($item['parent'] == $value){
                            $items[] = $item;  
                        }
                    }
                    break;
                }
            }
        }

        return Utilities::customJsonEncode($items);
    }

    public function actionGetLookupRecords($lookup_form_id, $lookup_id_field, $helper_field = null, $q = null, $id = null){
        Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
        $out = ['results' => ['id' => '', 'text' => '']];
        if (! is_null($q)) {
            $selection = [$lookup_id_field, '_id' => 0];
            $filter = [
                '$or' => [
                    [
                        $lookup_id_field => [
                            '$regex' => $q,
                            '$options' => 'i'
                        ]
                    ]
                ]
            ];
            if($helper_field){
                $selection[] = $helper_field;
                $filter['$or'][] = [
                    $helper_field => [
                        '$regex' => $q,
                        '$options' => 'i'
                    ]
                ];
            }

            // If the form is Global, the user can see all data
            $search_filters = Utilities::getFormType($lookup_form_id) == 'global' ?
                $filter :
                Utilities::getDataFiltersAccordingToActiveNode($filter);

            $query = new Query;
            $res = $query
                ->from('forms_' . $lookup_form_id)
                ->select($selection)
                ->where($search_filters)
                ->limit(1000)
                ->all();

            $data = [];
            if($res){
                foreach($res as $item){
                    $data[] = [
                        'id' => $item[$lookup_id_field],
                        'text' => $item[$lookup_id_field] . ($helper_field != null ? ' (' . $item[$helper_field] . ')' : '')
                    ];
                }
            }
            $out['results'] = array_values($data);
        }
        return $out;
    }

    public function actionUpdateForm($id){
        // Only Admin can update forms
        // The form can be updated only if the form is active and there isn't any active campaign related to this form
        if(! Yii::$app->user->can('Admin') || ! Utilities::canUpdateForm($id)){
            return $this->redirect(['index']);
        }

        $formIdObject = Utilities::getIdAsObject($id);
        $res = Utilities::getActiveVersionOfForm($id);
        $form = Form::findOne($id);

        if(Yii::$app->request->isPost){
            Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
            $data = Yii::$app->request->post();
            
            $form->name = $data['form_name'];
            $form->type = $data['form_type'];
            $form->directionality = $data['form_direction'];
            $form->save();

            $form_data = json_decode($data['formData']);
            
            $collection = Yii::$app->mongodb->getCollection('formsVersions');   

            $collection->update([
                'formId' => $formIdObject,
                'status' => 'Active'
            ], [
                '$set' => [
                    'status' => 'Inactive'
                ],
            ]);

            $result = $collection->insert([
                'formId' => $formIdObject,
                'createdAt' => Utilities::getDateTime(),
                'versionNumber' => (int)$res['versionNumber'] + 1,
                'status' => 'Active',
                'fields' => $form_data
            ]);
    
            if($result){
                // Check if form contains Lookup field
                Utilities::checkForLookupFieldAndInsertItToLookupCollections($id, json_decode($data['formData'], true));
                
                // Save columns in formsAndViewsNeededColumns collection
                $this->saveFormColumnsForDataTable($formIdObject, json_decode($data['formData'], true));

                Yii::$app->session->setFlash('form_saved', Yii::t('app', 'The form has been saved successfully'));
                return json_encode(['status' => true, 'formId' => $result]);
            }
            return json_encode(['status' => false]);
        }
        
        $fields = $res['fields'];
        $matrix_fields = [];
        $lookup_fields = [];
        
        // This variable indicates if the field has been used in submissions, so we prevent delete it (deactivate instead)
        $fields_have_been_used = [];

        foreach($fields as $index => $field){
            if($field['type'] == 'matrix'){
                if(isset($field['maxRecordsCount'])){
                    $fields[$index]['maxRecordsCount'] = (string)$field['maxRecordsCount']; // Casting to string to avoid input error
                }
                foreach($field['values'] as $index => $value){
                    if(Utilities::fieldTypeIsMultipleOptions($value['value'])){
                        $matrix_fields[$field['name']][] = [$index => $value['multipleOptions']];
                    }
                }
            }
            elseif($field['type'] == 'calculated'){
                $labeled_arithmetic_expression = $field['arithmeticExpression'];
                if(preg_match_all(Utilities::getCalculatedFieldExpressionPatern(), $field['arithmeticExpression'], $matches)){
                    foreach($matches[0] as $match){
                        $temp_match = str_replace('[', '', str_replace(']', '', $match));
                        foreach($fields as $temp_field){
                            if($temp_field['name'] == $temp_match){
                                $labeled_arithmetic_expression = str_replace($temp_match, $temp_field['label'], $labeled_arithmetic_expression);
                                break;
                            }
                        }
                    }
                }
                $fields[$index]['labeledArithmeticExpression'] = str_replace('[', '', str_replace(']', '', $labeled_arithmetic_expression));
            }
            elseif($field['type'] == 'lookup'){
                $lookup_fields[$field['name']] = json_decode($this->actionGetFormFields($field['form']), true);
            }

            if(Utilities::fieldHasBeenUsed($id, $field['name'])){
                $fields_have_been_used[] = $field['name'];
            }
        }
        
        return $this->render('update-form', [
            'fields' => Utilities::customJsonEncode($fields),
            'matrix_fields' => Utilities::customJsonEncode($matrix_fields),
            'all_forms' => Utilities::customJsonEncode(Utilities::getAllForms()),
            'lookup_fields' => Utilities::customJsonEncode($lookup_fields),
            'model' => $form,
            'fields_have_been_used' => Utilities::customJsonEncode($fields_have_been_used),
        ]);
    }

    public function getMatricesNames($columns){
        $matrices = [];
        foreach(array_keys($columns) as $column){
            if(Utilities::isMatrix($column)){
                $matrices[] = $column;
            }
        }
        return $matrices;
    }

    public function getFormFieldsNamesAndLabels($form_id){
        $versions = (new Query())
            ->from('formsVersions')
            ->where([
                'formId' => Utilities::getIdAsObject($form_id)
            ])
            ->all();

        $columns = [];
        foreach($versions as $version){  // Reverse versions in order to get the latest label of a field
            foreach($version['fields'] as $field){
                if(! Utilities::isHeader($field['name']) && ! Utilities::isParagraph($field['name'])){
                    $columns[$field['name']] = $field['label'];
                }
            }
        }
        return $columns;
    }

    public function actionSubmissions($id){
        // Admin can see all data
        // Normal user can see only the data in assigned nodes
        if(! Yii::$app->user->can('Admin')){
            if(! Utilities::checkPermissionForForm($id, 'read')){
                return $this->redirect(['index']);
            }
        }

        // Check form status (if it's inactive, the form's records mustn't be shown)
        if(! Utilities::formIsActive($id)){
            return $this->redirect(['index']);
        }

        $columns = $this->getDataTableNeededColumns($id);

        return $this->render('form-submissions', [
            'columns_names'     => Utilities::customJsonEncode($columns['columnsNames']),
            'columns_labels'    => $columns['columnsLabels'],
            'form_id'           => json_encode($id),
            'form_name'         => Utilities::getFormName($id)
        ]);
    }

    public function actionGetFormSubmissionsData($form_id, $start, $length){
        $columns = Yii::$app->request->get()['columns'];
        $search_and_sort = Utilities::handleDataTableSearchAndSort($columns, Yii::$app->request->get()['order'] ?? null);
        $search_values = $search_and_sort['search'];
        $sort_values = $search_and_sort['sort'];

        // The user can only see the data in his/her node and its children
        // Or if the form is Global, the user can see all data
        $form_type = Utilities::getFormType($form_id);
        if($form_type == 'global'){
            $filters = $search_values;
        }
        else{
            $filters = Utilities::getDataFiltersAccordingToActiveNode($search_values);
        }

        $res = (new Query())
            ->from('forms_' . $form_id)
            ->select(Utilities::getProjectionFields())
            ->where($filters)
            ->orderBy($sort_values)
            ->offset($start)
            ->limit($length)
            ->all();
        
        $form_columns = $this->getDataTableNeededColumns($form_id)['columnsNames'];

        $data = [];
        if($res){
            foreach($res as $index => $item){
                $data[$index][] = Utilities::getDataTableViewRecordLink($form_id, $item['_id']);
                foreach($form_columns as $form_column){
                    if(Utilities::isLookup($form_column)){
                        if(isset($item[$form_column])){
                            $lookup_data = Utilities::getLookupFieldData($form_id, $form_column, $item[$form_column]);
                            $data[$index][] = Utilities::getDataTableViewRecordLink($lookup_data['form'], $lookup_data['document']['_id'], $item[$form_column]);
                        }
                        else{
                            $data[$index][] = Utilities::getNotSetSpan();
                        }
                    }
                    else{
                        $data[$index][] = $item[$form_column] ?? Utilities::getNotSetSpan();
                    }
                }
            }
        }

        $count = (new Query())
            ->from('forms_' . $form_id)
            ->where($filters)
            ->count();

        return Utilities::customJsonEncode([
            'recordsTotal' => $count,
            'recordsFiltered' => $count,
            'data' => $data
        ]);
    }

    public function actionViewRecord($form_id, $document_id){
        // The user can only view the records in forms in his/her assigned groups
        if(! Yii::$app->user->can('Admin')){
            // This checks the accessibility of form records at all
            if(! Utilities::checkPermissionForForm($form_id, 'read')){
                return $this->redirect(['index']);
            }
        }

        $columns = $this->getFormFieldsNamesAndLabels($form_id);
        $res = Utilities::getSpecificDocument($form_id, $document_id);
            
        $data = [];
        if($res){

            // This checks the record accessibility according to node
            // (The user can access form submissions if he/she has a read permission, but if he/she tries to access specific record by typing its id in url, we have to check if he/she can view this record according to nodes tree)
            $nodes = Utilities::getNodeAndItsChildrenIDs();
            if(! in_array($res['ownerNodeId'], $nodes)){
                return $this->redirect(['index']);
            }

            $files = [];

            foreach($columns as $key => $value){
                if(isset($res[$key])){
                    if(Utilities::isLookup($key)){
                        // If field is lookup, we display a link to referrence record, and if there are read-only-fields (helper-fields) we display it also
                        $lookup_data = Utilities::getLookupFieldData($form_id, $key, $res[$key]);
                        $content = '<p><b>' . Utilities::getDataTableViewRecordLink($lookup_data['form'], $lookup_data['document']['_id'], $res[$key]) . '</b></p>';

                        if($lookup_data['read_only_fields']){
                            // Get read only fields labels
                            $lookup_form_fields = $this->getFormFieldsNamesAndLabels($lookup_data['form']);
                            $content .= '<ul style="padding: 0 15px;">';
                            foreach($lookup_data['read_only_fields'] as $read_only_field){
                                $content .= '<li><b>' . $lookup_form_fields[$read_only_field] . '</b>: ' . (isset($lookup_data['document'][$read_only_field]) ? $lookup_data['document'][$read_only_field] : Utilities::getNotSetSpan()) . '</li>';
                            }
                            $content .= '</ul>';
                        }

                        $data[] = [
                            'attribute' => $value,
                            'value'     => $content,
                            'format'    => 'raw'
                        ];
                        
                    }
                    elseif(Utilities::isStarRating($key)){
                        $data[] = [
                            'attribute' => $value,
                            'format' => 'raw',
                            'value' => StarRating::widget([
                                'name' => 'star-rating',
                                'value' => $res[$key],
                                'pluginOptions' => [
                                    'showCaption' => false,
                                    'displayOnly' => true,
                                ]
                            ])
                        ];
                    }
                    elseif(Utilities::isFile($key)){
                        $file_record = \app\models\File::findOne($res[$key]);
                        // Check if the field is required in order to allow/prevent deleting the file
                        $active_version_fields = Utilities::getActiveVersionOfForm($form_id)['fields'];
                        $is_required = false;
                        foreach($active_version_fields as $active_version_field){
                            if($key == $active_version_field['name']){
                                if($active_version_field['required']){
                                    $is_required = true;
                                }
                                break;
                            }
                        }
                        $files[$value] = [
                            'field_name' => $key,
                            'file_record' => $file_record,
                            'is_required' => $is_required,
                        ];
                    }
                    elseif(! Utilities::isMatrix($key)){
                        $data[] = [
                            'attribute' => $value,
                            'value' => is_array($res[$key]) ? implode(', ', $res[$key]) : $res[$key],
                        ];
                    }
                }
                elseif(Utilities::isFile($key)){    // Allow user uploading file fields even if it doens't exist in the submitted record
                    $files[$value] = [
                        'field_name'    => $key,
                        'file_record'   => null,
                        'is_required'   => true,
                    ];
                }
            }

            // Get the matrices fields if any
            $matrices = $this->getMatricesNames($columns);
            if($matrices){
                foreach($matrices as $matrix){
                    $matrix_res = (new Query())
                        ->from($matrix)
                        ->where([
                            'id' => Utilities::getIdAsObject($document_id)
                        ])
                        ->all();

                    if($matrix_res){
                        $matrix_label = $columns[$matrix];
                        $table = Utilities::getMatrixDataAsTable($form_id, $matrix, $matrix_res);
                        $data[] = [
                            'attribute' => $matrix,
                            'label'     => $matrix_label . '<span class="not-set"> (Matrix Field) </span>',
                            'format'    => 'raw',
                            'value'     => $table,
                        ];
                    }
                }
            }

            // Check if the record has children records from other forms
            $lookup_res = (new Query())
                ->from('lookupMap')
                ->where([
                    'referrenceFormId' => Utilities::getIdAsObject($form_id)
                ])
                ->all();
            $children_data = [];
            $children_forms_IDs = [];
            if($lookup_res){
                foreach($lookup_res as $lookup_item){
                    $children_res = (new Query())
                        ->from('forms_' . (string)$lookup_item['formId'])
                        ->select(Utilities::getProjectionFields())
                        ->where([
                            $lookup_item['lookupFieldName'] => $res[$lookup_item['referrenceFieldName']]
                        ])
                        ->andWhere(Utilities::getDataFiltersAccordingToActiveNode([]))
                        ->all();
                    
                    $form_fields_data = [];
                    if($children_res){
                        $form_fields = $this->getFormFieldsNamesAndLabels((string)$lookup_item['formId']);
                        $visible_child_form_fields = Utilities::checkIfChildFormFieldsVisibilityHasManaged($form_id, (string)$lookup_item['formId']);
                        if($visible_child_form_fields && $visible_child_form_fields['fields']){
                            foreach($children_res as $index => $child_res){
                                // Display only 5 results, the rest can be displayed by clicking on 'View All'
                                if($index < 5){
                                    // Append document id to be used in view record icon
                                    $form_fields_data['_id'][] = (string)$child_res['_id'];
                                    foreach($form_fields as $form_field_name => $form_field_label){
                                        if(in_array($form_field_name, $visible_child_form_fields['fields'])){
                                            $form_fields_data[$form_field_label][] = isset($child_res[$form_field_name]) ? $child_res[$form_field_name] : null;
                                        }
                                    }
                                }
                                else{
                                    break;
                                }
                            }
                        }
                    }
                    $children_data[Utilities::getFormName((string)$lookup_item['formId'])] = $form_fields_data;
                    $children_forms_IDs[] = [
                        'form_id'           => (string)$lookup_item['formId'],
                        'referrence_field'  => $lookup_item['referrenceFieldName'],
                        'lookup_field'      => $lookup_item['lookupFieldName'],
                        'value'             => $res[$lookup_item['referrenceFieldName']]
                    ];
                }
            }
        }
        
        return $this->render('view', [
            'data' => $data,
            'children_data' => $children_data,
            'form_id' => $form_id,
            'document_id' => $document_id,
            'children_forms_IDs' => $children_forms_IDs,
            'record' => $res,
            'files' => $files,
        ]);
    }

    public function actionUpdateRecord($form_id, $document_id){
        // The user can only update records in forms in his/her assigned groups
        if(! Yii::$app->user->can('Admin')){
            if(! Utilities::checkPermissionForForm($form_id, 'update')){
                return $this->redirect(['index']);
            }
        }

        $document = Utilities::getSpecificDocument($form_id, $document_id);

        // This checks the record accessibility according to node
        // (The user can access form submissions if he/she has a read permission, but if he/she tries to access specific record by typing its id in url, we have to check if he/she can view this record according to nodes tree)
        $nodes = Utilities::getNodeAndItsChildrenIDs();
        if(! in_array($document['ownerNodeId'], $nodes)){
            return $this->redirect(['index']);
        }

        // We have to check if the record is completed firstly
        if(isset($document['isCompleted']) && $document['isCompleted'] == false){
            return $this->render('record-must-be-completed', [
                'campaign_id' => (string)$document['campaignId'],
                'document_id' => $document_id,
                'form_id' => $form_id
            ]);
        }

        $form = Utilities::getActiveVersionOfForm($form_id);
        
        // Exclude file fields because it can be updated from view record page directly
        $fields_without_files = [];
        foreach($form['fields'] as $field){
            if($field['type'] != 'file'){
                $fields_without_files[] = $field;
            }
        }
        
        $all_fields = FormHelpers::prepareFields($form_id, $fields_without_files, $form['versionNumber'], $document);
        $form_fields = $all_fields['form_fields'];
        $other_fields = $all_fields['other_fields'];
        $model = $form_fields[0]::$model;

        if (Yii::$app->request->isAjax) {
            $model->load(Yii::$app->request->post());
            Yii::$app->response->format = Response::FORMAT_JSON;
            return \yii\widgets\ActiveForm::validate($model);
        }
        
        if(Yii::$app->request->isPost){
            $data = Yii::$app->request->post();

            if($model->load($data) && $model->validate()){
                
                $dynamic_model_data = null;
                $matrix_data = [];
                FormHelpers::extractSubmittedData($data, $dynamic_model_data, $matrix_data);

                $submitted_data = [];
                FormHelpers::handleSubmittedFields($dynamic_model_data, $submitted_data, $form_id, $form['versionNumber']);
                
                $temp_matrix_data = [];
                FormHelpers::handleSubmittedMatrixFields($matrix_data, $temp_matrix_data);
                
                $saved_document_id = $this->saveSubmittedData($form_id, null, $submitted_data, true, $document_id);
                if($saved_document_id){
                    foreach($temp_matrix_data as $matrix_name => $item){
                        $this->saveSubmittedMatrixData($saved_document_id, $matrix_name, $item, true, $form_id);
                    }
                }
                $save_and_new = 'save-and-new';
                if(isset($data[$save_and_new])){
                    return $this->redirect(['render-form', 'id' => $form_id]);
                }
                return $this->redirect(['view-record', 'form_id' => $form_id, 'document_id' => $document_id]);
            }
        }

        // Get the submitted matrix records
        $matrices_results = FormHelpers::handleMetricesForUpdateAndCompleteRecord($other_fields, $document_id);
        
        // Select fields must be filled-out with the appropriate data according to its parents dropdown fields (related lists)
        $list_values = FormHelpers::handleRelatedListsForUpdateAndCompleteRecord($form_id, $form_fields, $document);
        
        // Show if fields: We have to display the fields those are hidden according to an option
        $show_if_fields = FormHelpers::handleShowIfForUpdateAndCompleteRecord($form_fields);

        return $this->render('render-form', [
            'form_fields'       => $form_fields,
            'other_fields'      => $other_fields,
            'direction'         => Utilities::getFormDirectionality($form_id),
            'form_id'           => $form_id,
            'matrices_results'  => Utilities::customJsonEncode($matrices_results),
            'list_values'       => Utilities::customJsonEncode($list_values),
            'show_if_fields'    => Utilities::customJsonEncode($show_if_fields),
        ]);
    }
	
    // This function is used to fetch all forms in the system in order to display it when the Admin adds Lookup field
	public function actionGetAllForms(){
		header('Access-Control-Allow-Origin: *');
		$res = (new Query())
			->from('forms')
			->select(['name'])
			->all();
		
		if($res){
			$data = [];
			foreach($res as $item){
				$data[] = [
					'id' => (string)$item['_id'],
					'name' => $item['name']
				];
			}
			return Utilities::customJsonEncode([
				'status' => true,
				'data' => $data
			]);
		}
		return json_encode([
			'status' => false,
			'message' => 'No forms found!'
		]);
    }
	
    // This function is used to get the fields of a form in order to display it in Lookup field
    // the function loop through the fields of the selected form in order to:
    // - determin reference fields which are used as foriegn key
    // - read only fields which are used to be displayed alongside with the reference field 
	public function actionGetFormFields($id){
		header('Access-Control-Allow-Origin: *');
		$versions = (new Query())
			->from('formsVersions')
			->where([
				'formId' => Utilities::getIdAsObject($id)
			])
			->all();
		
		$reference_fields = [];
		$temp_reference_fields = [];
		$read_only_fields = [];
		$temp_read_only_fields = [];

        $active_version_fields = [];

		foreach($versions as $version){
			foreach($version['fields'] as $field){
				if($field['type'] != 'matrix' && $field['type'] != 'id' && $field['type'] != 'header' && $field['type'] != 'paragraph' && ! in_array($field['name'], $temp_read_only_fields)){
					$temp_read_only_fields[] = $field['name'];
					$read_only_fields[] = [
						'name' => $field['name'],
						'label' => $field['label'],
					];
				}
				if(! in_array($field['name'], $temp_reference_fields) && ($field['type'] == 'id' || ($field['type'] == 'text' && isset($field['unique']) && $field['unique']))){
					$temp_reference_fields[] = $field['name'];
					$reference_fields[] = [
						'name' => $field['name'],
						'label' => $field['label']
					];
				}

                if($version['status'] == 'Active'){
                    $active_version_fields[] = $field['name'];
                }
			}
        }

        // Check if the fields are in the active version in order to add 'deleted' label for old fields
        foreach($read_only_fields as $index => $read_only_field){
            if(! in_array($read_only_field['name'], $active_version_fields)){
                $read_only_fields[$index]['label'] = $read_only_field['label'] . ' (DELETED)';
            }
        }

        // Alphabetical order
        usort($read_only_fields, function($a, $b){
            // The callback must return -1, 0 or 1 according to comparison
            // Spaceship operator <=> does that!
            return $a['label'] <=> $b['label'];
        });
		
		return Utilities::customJsonEncode([
			'status' => true,
			'reference_fields' => $reference_fields,
			'read_only_fields' => $read_only_fields
		]);
    }
    
    // Change the form type (global, restricted ..)
    public function actionChangeType($id){
        if(Yii::$app->request->isAjax){
            Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
            $data = Yii::$app->request->post();
            $type = $data['Form']['type'];
            $form = Form::findOne($id);
            if($form){
                $form->type = $type;
                if($form->save()){
                    return ['data' => $form->type];
                }
                else{
                    return var_dump($form->getErrors());
                }
            }
        }
    }

    // Change the form status (active, inactive)
    public function actionChangeStatus($id, $action){
        if(Yii::$app->request->isPost){
            $form = Form::findOne($id);
            if($action == 'activate'){
                $form->status = 'Active';
                if($form->save()){
                    Yii::$app->session->setFlash('form_status_changed', 'The status of the form has been changed successfully');
                    return $this->redirect(['index']);
                }
            }
            else{
                // Check if there any active campaign
                $res = (new Query())
                    ->from('campaigns')
                    ->where([
                        'formId' => Utilities::getIdAsObject($id),
                        'status' => 'Active'
                    ])
                    ->one();
                if($res){
                    Yii::$app->session->setFlash('active_campaign_found', 'There is an active campaign at least related to this form, you have to terminate it firstly');
                    Yii::$app->session->setFlash('active_campaign_found_form_id', (string)$id);
                    return $this->redirect(['index']);
                }
                
                $form->status = 'Inactive';
                if($form->save()){
                    Yii::$app->session->setFlash('form_status_changed', 'The status of the form has been changed successfully');
                    return $this->redirect(['index']);
                }
            }
        }
    }

    public function actionViewAllChildRecords($form_id, $field_name, $value, $parent_form_id){
        // Admin can see all data
        // Normal user can see only the data in assigned nodes
        if(! Yii::$app->user->can('Admin')){
            if(! Utilities::checkPermissionForForm($form_id, 'read')){
                return $this->redirect(['index']);
            }
        }

        $res = (new Query())
            ->from('childrenFormsVisibleFields')
            ->where([
                'parentFormId' => Utilities::getIdAsObject($parent_form_id),
                'childFormId' => Utilities::getIdAsObject($form_id)
            ])
            ->one();

        $columns_names_and_labels = $this->getFormFieldsNamesAndLabels($form_id);
        $columns = [];
        if($res){
            foreach($res['fields'] as $field){
                $columns[$field] = $columns_names_and_labels[$field];
            }
        }

        return $this->render('view-all-child-records', [
            'columns_names' => Utilities::customJsonEncode(array_keys($columns)),
            'columns_labels' => array_values($columns),
            'form_id' => Utilities::customJsonEncode($form_id),
            'field_name' => Utilities::customJsonEncode($field_name),
            'value' => Utilities::customJsonEncode($value),
            'parent_form_id' => Utilities::customJsonEncode($parent_form_id),
        ]);
    }

    public function actionViewAllChildRecordsData($form_id, $start, $length, $field_name, $value, $parent_form_id){
        $columns = Yii::$app->request->get()['columns'];
        $search_and_sort = Utilities::handleDataTableSearchAndSort($columns, Yii::$app->request->get()['order'] ?? null);
        $search_values = $search_and_sort['search'];
        $sort_values = $search_and_sort['sort'];

        // The user can only see the data in his/her node and its children
        // Or if the form is Global, the user can see all data
        $form_type = Utilities::getFormType($form_id);
        if($form_type == 'global'){
            $filters = $search_values;
        }
        else{
            $filters = Utilities::getDataFiltersAccordingToActiveNode($search_values);
        }

        $res = (new Query())
            ->from('forms_' . $form_id)
            ->select(Utilities::getProjectionFields())
            ->where([
                $field_name => $value
            ])
            ->andWhere($filters)
            ->orderBy($sort_values)
            ->offset($start)
            ->limit($length)
            ->all();
        
        $columns_res = (new Query())
            ->from('childrenFormsVisibleFields')
            ->where([
                'parentFormId' => Utilities::getIdAsObject($parent_form_id),
                'childFormId' => Utilities::getIdAsObject($form_id)
            ])
            ->one();

        $data = [];
        if($res){
            foreach($res as $index => $item){
                $data[$index][] = Utilities::getDataTableViewRecordLink($form_id, $item['_id']);
                foreach($columns_res['fields'] as $field){
                    if(Utilities::isLookup($field)){
                        $lookup_data = Utilities::getLookupFieldData($form_id, $field, $item[$field]);
                        $data[$index][] = Utilities::getDataTableViewRecordLink($lookup_data['form'], $lookup_data['document']['_id'], $item[$field]);
                    }
                    else{
                        $data[$index][] = $item[$field] ?? Utilities::getNotSetSpan();
                    }
                }
            }
        }
        
        $count = (new Query())
            ->from('forms_' . $form_id)
            ->where([
                $field_name => $value
            ])
            ->andWhere($filters)
            ->count();

        return Utilities::customJsonEncode([
            'recordsTotal' => $count,
            'recordsFiltered' => $count,
            'data' => $data
        ]);
    }

    public function actionManageChildrenFormsVisibleFields($id){
        $form = Form::findOne($id);
        $res = (new Query())
            ->from('lookupMap')
            ->where([
                'referrenceFormId' => Utilities::getIdAsObject($id)
            ])
            ->all();

        $data = [];
        if($res){
            foreach($res as $child_form){
                $child_form_id = $child_form['formId'];

                $child_res = (new Query())
                    ->from('childrenFormsVisibleFields')
                    ->where([
                        'parentFormId' => Utilities::getIdAsObject($id),
                        'childFormId' => Utilities::getIdAsObject($child_form_id),
                    ])
                    ->one();

                $choosen_fields = [];
                if($child_res && $child_res['fields']){
                    $fields_names_and_labels = $this->getFormFieldsNamesAndLabels($child_form_id);
                    foreach($fields_names_and_labels as $field_name => $field_label){
                        if(in_array($field_name, $child_res['fields'])){
                            $choosen_fields[$field_name] = $field_label;
                        }
                    }
                }

                $data[] = [
                    'child_form_id' => $child_form_id,
                    'child_form_name' => Utilities::getFormName($child_form_id),
                    'lookup_field_name' => $child_form['lookupFieldName'],
                    'choosen_form_fields' => $choosen_fields,
                ];
            }
        }
        
        return $this->render('manage-children-forms-visible-fields', [
            'form' => $form,
            'data' => $data
        ]);
    }

    public function actionManageChildFormFields($id, $lookup_field_name, $parent_form_id){
        if(Yii::$app->request->isPost){
            $data = Yii::$app->request->post();
            $fields = $data['fields'] ?? null;

            $collection = Yii::$app->mongodb->getCollection('childrenFormsVisibleFields');
            $collection->update([
                'parentFormId' => Utilities::getIdAsObject($parent_form_id),
                'childFormId' => Utilities::getIdAsObject($id),
                'lookupFieldName' => $lookup_field_name
            ], [
                'parentFormId' => Utilities::getIdAsObject($parent_form_id),
                'childFormId' => Utilities::getIdAsObject($id),
                'lookupFieldName' => $lookup_field_name,
                'fields' => $fields
            ], [
                'upsert' => true
            ]);

            return $this->redirect(['manage-children-forms-visible-fields', 'id' => $parent_form_id]);
        }

        $child_form_fields = $this->getFormFieldsNamesAndLabels($id);
        $fields = [];
        // Execlude matrices fields and the referrence field of the parent form
        foreach($child_form_fields as $child_form_field_name => $child_form_field_label){
            if(! Utilities::isMatrix($child_form_field_name) && ! Utilities::isHeader($child_form_field_name) && ! Utilities::isParagraph($child_form_field_name) && ! Utilities::isFile($child_form_field_name) && $child_form_field_name != $lookup_field_name){
                $fields[$child_form_field_name] = $child_form_field_label;
            }
        }

        $selected_fields = [];
        $res = (new Query())
            ->from('childrenFormsVisibleFields')
            ->where([
                'parentFormId' => Utilities::getIdAsObject($parent_form_id),
                'childFormId' => Utilities::getIdAsObject($id),
            ])
            ->one();
        if($res){
            $selected_fields = $res['fields'];
        }

        return $this->renderAjax('manage-child-form-visible-fields-modal', [
            'id' => $id,
            'fields' => $fields,
            'selected_fields' => $selected_fields
        ]);
    }

    // This function is used in create and update form in order to save form's columns in a collection
    // The saved columns will be used when the user displays form submissions
    // because the datatable requires the names of columns, so instead of fetching it by looping through form versions
    // we will get it directly from DB
    public function saveFormColumnsForDataTable($form_id, $fields){
        $columns = [];
        foreach($fields as $field){
            $field_name = $field['name'];
            if(! Utilities::isMatrix($field_name) && ! Utilities::isHeader($field_name) && ! Utilities::isParagraph($field_name) && ! Utilities::isLogo($field_name) && ! Utilities::isFile($field_name)){
                $columns[$field_name] = $field['label'];
            }
        }
        $collection = Yii::$app->mongodb->getCollection('dataTableNeededColumns');
        $collection->update([
            'formId' => Utilities::getIdAsObject($form_id),
        ], [
            'formId' => Utilities::getIdAsObject($form_id),
            'columnsNames' => array_keys($columns),
            'columnsLabels' => array_values($columns),
        ], [
            'upsert' => true
        ]);
    }

    public function getDataTableNeededColumns($form_id){
        $fields_selection_count = Utilities::getSubmissionsFieldsSelectionCount();
        $columns = (new Query())
            ->from('dataTableNeededColumns')
            ->where([
                'formId' => Utilities::getIdAsObject($form_id),
            ])
            ->one();

        $needed_columns = [];
        foreach($columns['columnsNames'] as $index => $column){
            if($index >= $fields_selection_count){
                break;
            }
            $needed_columns['columnsNames'][] = $column;
            $needed_columns['columnsLabels'][] = $columns['columnsLabels'][$index];
        }
        return $needed_columns;
    }

    // Handle the uploaded logo files if the form has logo field
    public function actionUploadLogoFile(){
        if(Yii::$app->request->isPost){
            $name = array_keys($_FILES);
            if($name){
                $name = $name[0];
                $file = UploadedFile::getInstanceByName($name);
                if($file){
                    $file_name = 'images/logo-files/';
                    if(! file_exists($file_name)){
                        mkdir($file_name, 0777, true);
                        $proper_file_name = str_replace(' ', '_', $file->baseName) . '_' . rand(1000, 100000) . '.' . $file->extension;
                        $file_name .= $proper_file_name;
                        if($file->saveAs($file_name)){
                            return $this->asJson([
                                'status' => true,
                                'path' => $file_name,
                            ]);
                        }
                        return $this->asJson([
                            'status' => false,
                            'message' => 'Geting error while uploading file!',
                        ]);
                    }
                }
                return $this->asJson([
                    'status' => false,
                    'message' => 'No file found!',
                ]);
            }
            return $this->asJson([
                'status' => false,
                'message' => 'No instance found!',
            ]);
        }
    }

    public function actionDownloadFile($id){
        $file_record = Utilities::getFileRecord($id);
        if($file_record){
            $path = Yii::getAlias('@webroot') . '/' . $file_record['path'];
            if (file_exists($path)){
                Yii::$app->response->sendFile($path);
            }
        }
    }

    // Upload file field of a record
    // The user can upload file field if the file doesn't exist in the record, or if the user deleted it previously
    public function actionUploadFile($form_id, $document_id, $file_field_name){
        $file_field = null;
        
        $form_active_version = Utilities::getActiveVersionOfForm($form_id);
        foreach($form_active_version['fields'] as $field){
            if($field['name'] == $file_field_name){
                $file_field = $field;
                break;
            }
        }

        $file_field_label = $file_field['label'];
        $dynamic_model = new \yii\base\DynamicModel();
        $dynamic_model->defineAttribute($file_field_name);
        $dynamic_model->addRule([$file_field_name], 'required', ['message' => $file_field_label . ' can not be blank']);
        if(isset($file_field['maxFileSize'])){
            $dynamic_model->addRule([$file_field_name], 'file', ['maxSize' => 1024 * 1024 * $file_field['maxFileSize']]);
        }
        if(isset($file_field['fileType'])){
            $extensions = Utilities::getExtensionsOfFileType($file_field['fileType']);
            $dynamic_model->addRule([$file_field_name], 'file', ['extensions' => $extensions]);
        }

        if($dynamic_model->load(Yii::$app->request->post())){
            $file = UploadedFile::getInstanceByName("DynamicModel[{$file_field_name}]");
            if($file){
                $file_name = 'files/' . $form_id;
                if(! file_exists($file_name)){
                    mkdir($file_name, 777);
                }
                $proper_file_name = str_replace(' ', '_', $file->baseName) . '_' . rand(1000, 100000) . '.' . $file->extension;
                $file_name .= '/' . $proper_file_name;
                if($file->saveAs($file_name)){
                    $file_data = [
                        'type' => $file_field['fileType'],
                        'size' => $file->size,
                        'extension' => $file->extension,
                        'path' => $file_name,
                        'formId' => Utilities::getIdAsObject($form_id),
                        'fieldName' => $file_field_name,
                    ];
                    $saved_file_id = Utilities::addRecordToFilesCollection($file_data);
                    
                    if($saved_file_id){
                        Utilities::addDocumentIdToSavedFiles([$saved_file_id], $document_id);
                        // Add file_id to document
                        $form_collection = Yii::$app->mongodb->getCollection('forms_' . $form_id);
                        $form_collection->update([
                            '_id' => Utilities::getIdAsObject($document_id),
                        ], [
                            '$set' => [
                                $file_field_name => $saved_file_id,
                            ]
                        ]);
                        Yii::$app->session->setFlash('file_uploaded', 'The file has been uploaded successflly');
                    }
                    else{
                        Yii::$app->session->setFlash('could_not_upload_file', 'Could not upload the file');
                    }
                    return $this->redirect(['view-record', 'form_id' => $form_id, 'document_id' => $document_id]);
                }
            }
        }

        return $this->renderAjax('_upload-file-form-modal', [
            'dynamic_model'     => $dynamic_model,
            'file_field_name'   => $file_field_name,
            'file_field_label'  => $file_field_label,
        ]);
    }

    // Update file field of a record
    // We must check for the rules of file like maxSize and extension
    public function actionUpdateFile($form_id, $document_id, $id){
        $file_record = Utilities::getFileRecord($id);
        $file_field_name = $file_record['fieldName'];
        $file_field = null;
        
        $form_active_version = Utilities::getActiveVersionOfForm($form_id);
        foreach($form_active_version['fields'] as $field){
            if($field['name'] == $file_field_name){
                $file_field = $field;
                break;
            }
        }

        $file_field_label = $file_field['label'];
        $dynamic_model = new \yii\base\DynamicModel();
        $dynamic_model->defineAttribute($file_field_name);
        $dynamic_model->addRule([$file_field_name], 'required', ['message' => $file_field_label . ' can not be blank']);
        if(isset($file_field['maxFileSize'])){
            $dynamic_model->addRule([$file_field_name], 'file', ['maxSize' => 1024 * 1024 * $file_field['maxFileSize']]);
        }
        if(isset($file_field['fileType'])){
            $extensions = Utilities::getExtensionsOfFileType($file_field['fileType']);
            $dynamic_model->addRule([$file_field_name], 'file', ['extensions' => $extensions]);
        }

        if($dynamic_model->load(Yii::$app->request->post())){
            $file = UploadedFile::getInstanceByName("DynamicModel[{$file_field_name}]");
            if($file){
                $file_name = 'files/' . $form_id;
                $proper_file_name = str_replace(' ', '_', $file->baseName) . '_' . rand(1000, 100000) . '.' . $file->extension;
                $file_name .= '/' . $proper_file_name;
                if($file->saveAs($file_name)){
                    $files_collection = Yii::$app->mongodb->getCollection('filesCollection');
                    $updated = $files_collection->update([
                        '_id' => Utilities::getIdAsObject($id),
                    ], [
                        '$set' => [
                            'size' => $file->size,
                            'extension' => $file->extension,
                            'path' => $file_name,
                            'lastUpdatedAt' => Utilities::getDateTime(),
                            'lastUpdatedBy' => Utilities::getIdAsObject(Yii::$app->user->getId()),
                        ]
                    ]);
                    if($updated){
                        Yii::$app->session->setFlash('file_updated', 'The file has been updated successflly');
                    }
                    else{
                        Yii::$app->session->setFlash('could_not_update_file', 'Could not update the file');
                    }
                    return $this->redirect(['view-record', 'form_id' => $form_id, 'document_id' => $document_id]);
                }
            }
        }

        return $this->renderAjax('_upload-file-form-modal', [
            'dynamic_model' => $dynamic_model,
            'file_field_name' => $file_field_name,
            'file_field_label' => $file_field_label,
        ]);
    }

    // Delete file field of a record
    // The file can be deleted only if the field isn't required, if it's required the user must update it instead of deleting
    public function actionDeleteFile($form_id, $document_id, $id){
        if(Yii::$app->request->isPost){
            if(($file = \app\models\File::findOne($id)) === null){
                throw new NotFoundHttpException(Yii::t('app', 'The requested page does not exist.'));
            }
            
            $file_field_name = $file->fieldName;
            if($file->delete()){
                $form_collection = Yii::$app->mongodb->getCollection('forms_' . $form_id);
                $form_collection->update([
                    '_id' => Utilities::getIdAsObject($document_id),
                ], [
                    '$unset' => [
                        $file_field_name => null,
                    ]
                ]);
                Yii::$app->session->setFlash('file_deleted', 'The file has been deleted successflly');
            }
            else{
                Yii::$app->session->setFlash('could_not_delete_file', 'Could not delete the file');
            }
            return $this->redirect(['view-record', 'form_id' => $form_id, 'document_id' => $document_id]);
        }
    }

    public function actionDelete($id){
        $collection = Yii::$app->mongodb->getCollection('forms');
        $collection->remove(['_id' => Utilities::getIdAsObject($id)]);
        return $this->redirect(['index']);
    }

    public function actionShowCreateViewModal($form_id){
        $model = new \app\models\View();

        if($model->load(Yii::$app->request->post())){
            return $this->redirect(['/views/builder', 'form_id' => $form_id, 'domain' => $model->domain]);
        }

        return $this->renderAjax('create-view-modal', [
            'model' => $model,
            'domains' => Utilities::checkFormAvailableDomains($form_id)
        ]);
    }
}