/** Refreshes weights list and remembers previous selection if
 weights choice is still there and a selection was previously made */
void FieldNewCalcRateDlg::InitWeightsList()
{
	boost::uuids::uuid old_id = GetWeightsId();
	w_ids.clear();
	w_man_int->GetIds(w_ids);
	m_weights->Clear();
	for (size_t i=0; i<w_ids.size(); ++i) {
		m_weights->Append(w_man_int->GetLongDispName(w_ids[i]));
	}
	m_weights->SetSelection(wxNOT_FOUND);
	if (old_id.is_nil() && !w_man_int->GetDefault().is_nil()) {
		for (long i=0; i<w_ids.size(); ++i) {
			if (w_ids[i] == w_man_int->GetDefault()) {
				m_weights->SetSelection(i);
			}
		}
	} else if (!old_id.is_nil()) {
		for (long i=0; i<w_ids.size(); ++i) {
			if (w_ids[i] == old_id) m_weights->SetSelection(i);
		}
	}
}
void VariableSettingsDlg::OnOkClick(wxCommandEvent& event)
{
    wxLogMessage("Click VariableSettingsDlg::OnOkClick:");
	if (no_weights_found_fail) {
		event.Skip();
		EndDialog(wxID_CANCEL);
		return;
	}
	
    if ((style & ALLOW_EMPTY_IN_FIRST) && (style & ALLOW_EMPTY_IN_SECOND)) {
        if (lb1->GetSelection() == 0 && lb2->GetSelection() == 0) {
            wxString msg(_("No field chosen for first and second variable."));
            wxMessageDialog dlg (this, msg, _("Error"), wxOK | wxICON_ERROR);
            dlg.ShowModal();
            return;
        }
    }
    
    if (map_theme_ch) {
        m_theme = map_theme_ch->GetSelection();
    }
	
	if (lb1->GetSelection() == wxNOT_FOUND) {
		wxString msg(_("No field chosen for first variable."));
		wxMessageDialog dlg (this, msg, _("Error"), wxOK | wxICON_ERROR);
		dlg.ShowModal();
		return;
	}
    int sel_idx = lb1->GetSelection();
	v1_col_id = col_id_map[sel1_idx_map[sel_idx]];
    
	v1_name = table_int->GetColName(v1_col_id);
	project->SetDefaultVarName(0, v1_name);
	if (is_time) {
		v1_time = time_lb1->GetSelection();
		project->SetDefaultVarTime(0, v1_time);
		if (!table_int->IsColTimeVariant(v1_col_id))
            v1_time = 0;
	}
    wxLogMessage(v1_name);
    
	if (num_var >= 2) {
		if (lb2->GetSelection() == wxNOT_FOUND) {
			wxString msg(_("No field chosen for second variable."));
			wxMessageDialog dlg (this, msg, _("Error"), wxOK | wxICON_ERROR);
			dlg.ShowModal();
			return;
		}
        int sel_idx = lb2->GetSelection();
		v2_col_id = col_id_map[sel2_idx_map[sel_idx]];
		v2_name = table_int->GetColName(v2_col_id);
		project->SetDefaultVarName(1, v2_name);
		if (is_time) {
			v2_time = time_lb2->GetSelection();
			project->SetDefaultVarTime(1, v2_time);
			if (!table_int->IsColTimeVariant(v2_col_id))
                v2_time = 0;
		}
        wxLogMessage(v2_name);
	}
	if (num_var >= 3) {
		if (lb3->GetSelection() == wxNOT_FOUND) {
			wxString msg(_("No field chosen for third variable."));
			wxMessageDialog dlg (this, msg, _("Error"), wxOK | wxICON_ERROR);
			dlg.ShowModal();
			return;
		}
		v3_col_id = col_id_map[sel3_idx_map[lb3->GetSelection()]];
		v3_name = table_int->GetColName(v3_col_id);
		project->SetDefaultVarName(2, v3_name);
		if (is_time) {
			v3_time = time_lb3->GetSelection();
			project->SetDefaultVarTime(2, v3_time);
			if (!table_int->IsColTimeVariant(v3_col_id))
                v3_time = 0;
		}
        wxLogMessage(v3_name);
	}
	if (num_var >= 4) {
		if (lb4->GetSelection() == wxNOT_FOUND) {
			wxString msg(_("No field chosen for fourth variable."));
			wxMessageDialog dlg (this, msg, _("Error"), wxOK | wxICON_ERROR);
			dlg.ShowModal();
			return;
		}
		v4_col_id = col_id_map[sel4_idx_map[lb4->GetSelection()]];
		v4_name = table_int->GetColName(v4_col_id);
		project->SetDefaultVarName(3, v4_name);
		if (is_time) {
			v4_time = time_lb4->GetSelection();
			project->SetDefaultVarTime(3, v4_time);
			if (!table_int->IsColTimeVariant(v4_col_id))
                v4_time = 0;
		}
        wxLogMessage(v4_name);
	}
	
    wxString emptyVar = FillData();
    if (emptyVar.empty()== false) {
        wxString msg = wxString::Format(_("The selected variable %s is not valid. If it's a grouped variable, please modify it in Time->Time Editor. Or please select another variable."), emptyVar);
        wxMessageDialog dlg (this, msg.mb_str(), _("Invalid Variable"), wxOK | wxICON_ERROR);
        dlg.ShowModal();
        
    } else {
	
        if (show_weights) {
            project->GetWManInt()->MakeDefault(GetWeightsId());
        }
    	if (GetDistanceMetric() != WeightsMetaInfo::DM_unspecified) {
    		project->SetDefaultDistMetric(GetDistanceMetric());
    	}
    	if (GetDistanceUnits() != WeightsMetaInfo::DU_unspecified) {
    		project->SetDefaultDistUnits(GetDistanceUnits());
    	}
    	
        bool check_group_var = true;
        try {
            for (int i=0; i<col_ids.size(); i++) {
                project->GetTableInt()->GetColTypes(col_ids[i]);
            }
        } catch(GdaException& ex) {
            // place holder found
            wxString msg = wxString::Format(_("The selected group variable should contains %d items. Please modify the group variable in Time->Time Editor, or select another variable."), project->GetTableInt()->GetTimeSteps());
            wxMessageDialog dlg (this, msg.mb_str(), _("Incomplete Group Variable"), wxOK | wxICON_ERROR);
            dlg.ShowModal();
            check_group_var = false;
        }

        if (check_group_var == true)
            EndDialog(wxID_OK);
    }
}
void RangeSelectionDlg::OnAddNeighsToSelClick( wxCommandEvent& event )
{
	project->AddNeighborsToSelection(GetWeightsId());
}
void FieldNewCalcRateDlg::Apply()
{
	if (m_result->GetSelection() == wxNOT_FOUND) {
		wxString msg("Please select a results field.");
		wxMessageDialog dlg (this, msg, "Error", wxOK | wxICON_ERROR);
		dlg.ShowModal();
		return;
	}
	
	const int op = m_method->GetSelection();
	if ((op == 3 || op == 4) && GetWeightsId().is_nil()) {
		wxString msg("Weight matrix required for chosen spatial "
					 "rate method.");
		wxMessageDialog dlg (this, msg, "Error", wxOK | wxICON_ERROR);
		dlg.ShowModal();
		return;
	}
	
	if (m_event->GetSelection() == wxNOT_FOUND) {
		wxString msg("Please select an Event field.");
		wxMessageDialog dlg (this, msg, "Error", wxOK | wxICON_ERROR);
		dlg.ShowModal();
		return;
	}

	if (m_base->GetSelection() == wxNOT_FOUND) {
		wxString msg("Please select an Base field.");
		wxMessageDialog dlg (this, msg, "Error", wxOK | wxICON_ERROR);
		dlg.ShowModal();
		return;
	}
	
	const int result_col = col_id_map[m_result->GetSelection()];
	const int cop1 = col_id_map[m_event->GetSelection()];
	const int cop2 = col_id_map[m_base->GetSelection()];
	
	TableState* ts = project->GetTableState();
	wxString grp_nm = table_int->GetColName(result_col);
	if (!Project::CanModifyGrpAndShowMsgIfNot(ts, grp_nm)) return;
	
	if (is_space_time && !IsAllTime(result_col, m_result_tm->GetSelection()) &&
		(IsAllTime(cop1, m_event_tm->GetSelection()) ||
		 IsAllTime(cop2, m_base_tm->GetSelection())))
	{
		wxString msg("When \"all times\" selected for either variable, result "
					 "field must also be \"all times.\"");
		wxMessageDialog dlg (this, msg, "Error", wxOK | wxICON_ERROR);
		dlg.ShowModal();
		return;
	}

	boost::uuids::uuid weights_id = GetWeightsId();
	if (op == 3 || op == 4)	{
		if (!w_man_int->IsValid(weights_id)) {
			wxString msg("Was not able to load weights matrix.");
			wxMessageDialog dlg (this, msg, "Error", wxOK | wxICON_ERROR);
			dlg.ShowModal();
			return;
		}
	}

	std::vector<int> time_list;
	if (IsAllTime(result_col, m_result_tm->GetSelection())) {
		int ts = project->GetTableInt()->GetTimeSteps();
		time_list.resize(ts);
		for (int i=0; i<ts; i++) time_list[i] = i;
	} else {
		int tm = IsTimeVariant(result_col) ? m_result_tm->GetSelection() : 0;
		time_list.resize(1);
		time_list[0] = tm;
	}
	
	const int obs = table_int->GetNumberRows();
	
	bool Event_undefined = false;
	if (IsAllTime(cop1, m_event_tm->GetSelection())) {
		b_array_type undefined;
		table_int->GetColUndefined(cop1, undefined);
		int ts = project->GetTableInt()->GetTimeSteps();
		for (int t=0; t<ts && !Event_undefined; t++) {
			for (int i=0; i<obs && !Event_undefined; i++) {
				if (undefined[t][i]) Event_undefined = true;
			}
		}
	} else {
		std::vector<bool> undefined(obs);
		int tm = IsTimeVariant(cop1) ? m_event_tm->GetSelection() : 0;
		table_int->GetColUndefined(cop1, tm, undefined);
		for (int i=0; i<obs && !Event_undefined; i++) {
			if (undefined[i]) Event_undefined = true;
		}		
	}
	if (Event_undefined) {
		wxString msg("Event field has undefined values.  Please define "
					 "missing values or choose a different field.");
		wxMessageDialog dlg (this, msg, "Error", wxOK | wxICON_ERROR);
		dlg.ShowModal();
		return;
	}

	// for 
	HighlightState* highlight_state = project->GetHighlightState();
	std::vector<bool>& hs = highlight_state->GetHighlight();
	std::vector<bool> hs_backup = hs;

	for (int i=0; i<obs; i++) {
		hs[i] = true;
	}

	bool Base_undefined = false;
	if (IsAllTime(cop2, m_base_tm->GetSelection())) {
		b_array_type undefined;
		table_int->GetColUndefined(cop2, undefined);
		int ts = project->GetTableInt()->GetTimeSteps();
		for (int t=0; t<ts && !Base_undefined; t++) {
			for (int i=0; i<obs && !Base_undefined; i++) {
				if (undefined[t][i]) {
					Base_undefined = true;
					hs[i] = false;
				}
			}
		}
	} else {
		std::vector<bool> undefined(obs);
		int tm = IsTimeVariant(cop2) ? m_base_tm->GetSelection() : 0;
		table_int->GetColUndefined(cop2, tm, undefined);
		for (int i=0; i<obs && !Base_undefined; i++) {
			if (undefined[i]) {
				Base_undefined = true;
				hs[i] = false;
			}
		}
	}
	if (Base_undefined) {
		wxString msg("Base field has undefined values. Do you want to "
                     "save a subset without undefined values as a new "
                     "shape file? or please define "
					 "missing values or choose a different field.");
		wxMessageDialog dlg (this, msg, "Error", 
                             wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION);
        if (dlg.ShowModal() == wxID_YES) {
			ExportDataDlg dlg(this, project, true);
			dlg.ShowModal();
        }
		hs = hs_backup;
		return;
	}

	for (int i=0; i<obs; i++) {
		hs[i] = true;
	}

	bool Base_non_positive = false;
	if (IsAllTime(cop2, m_base_tm->GetSelection())) {
		d_array_type data;
		table_int->GetColData(cop2, data);
		int ts = project->GetTableInt()->GetTimeSteps();
		for (int t=0; t<ts && !Base_non_positive; t++) {
			for (int i=0; i<obs && !Base_non_positive; i++) {
				if (data[t][i] <= 0) {
					Base_non_positive = true;
					hs[i] = false;
				}
			}
		}
	} else {
		std::vector<double> data(obs);
		int tm = IsTimeVariant(cop2) ? m_base_tm->GetSelection() : 0;
		table_int->GetColData(cop2, tm, data);
		for (int i=0; i<obs && !Base_non_positive; i++) {
			if (data[i] <= 0) {
				Base_non_positive = true;
				hs[i] = false;
			}
		}
	}
	if (Base_non_positive) {
		wxString msg("Base field has zero or negative values, but all base "
					 "values must be strictly greater than zero. Do you want "
                     "to save a subset of non-zeros as a new shape file? ");
		wxMessageDialog dlg (this, msg, "Error", 
                             wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION);
		if (dlg.ShowModal() == wxID_YES) {
			ExportDataDlg exp_dlg(this, project, true);
			exp_dlg.ShowModal();
        }
		hs = hs_backup;
		return;
	}
	hs = hs_backup;

	bool has_undefined = false;
	double* B = new double[obs]; // Base variable vector == cop2
	double* E = new double[obs]; // Event variable vector == cop1
	double* r = new double[obs]; // result vector
	std::vector<double> data(obs);

	if (!IsAllTime(cop2, m_base_tm->GetSelection())) {
		int tm = IsTimeVariant(cop2) ? m_base_tm->GetSelection() : 0;
		table_int->GetColData(cop2, tm, data);
		for (int i=0; i<obs; i++) B[i] = data[i];
	}
	if (!IsAllTime(cop1, m_event_tm->GetSelection())) {
		int tm = IsTimeVariant(cop1) ? m_event_tm->GetSelection() : 0;
		table_int->GetColData(cop1, tm, data);
		for (int i=0; i<obs; i++) E[i] = data[i];
	}
	
	for (int t=0; t<time_list.size(); t++) {
		if (IsAllTime(cop2, m_base_tm->GetSelection())) {
			table_int->GetColData(cop2, time_list[t], data);
			for (int i=0; i<obs; i++) B[i] = data[i];
		}
		if (IsAllTime(cop1, m_event_tm->GetSelection())) {
			table_int->GetColData(cop1, time_list[t], data);
			for (int i=0; i<obs; i++) E[i] = data[i];
		}
		for (int i=0; i<obs; i++) r[i] = -9999;
	
		std::vector<bool> undef_r;
		switch (op) {
			case 0:
				GdaAlgs::RateSmoother_RawRate(obs, B, E, r, undef_r);
				break;
			case 1:
				GdaAlgs::RateSmoother_ExcessRisk(obs, B, E, r, undef_r);
				break;
			case 2:
				GdaAlgs::RateSmoother_EBS(obs, B, E, r, undef_r);
				break;
			case 3:
				has_undefined = GdaAlgs::RateSmoother_SRS(obs, w_man_int,
														  weights_id, B, E, r,
														  undef_r);
				break;
			case 4:
				has_undefined = GdaAlgs::RateSmoother_SEBS(obs, w_man_int,
														   weights_id, B, E, r,
														   undef_r);
				break;
			case 5:
				GdaAlgs::RateStandardizeEB(obs, B, E, r, undef_r);
				break;
			default:
				break;
		}
	
		for (int i=0; i<obs; i++) data[i] = r[i];
		table_int->SetColData(result_col, time_list[t], data);
		table_int->SetColUndefined(result_col, time_list[t], undef_r);

	}
	
	if (B) delete [] B; B = NULL;
	if (E) delete [] E; E = NULL;
	if (r) delete [] r; r = NULL;
	
	if (has_undefined) {
		wxString msg("Some calculated values were undefined and this is "
					 "most likely due to neighborless observations in the "
					 "weight matrix. Rate calculation successful for "
					 "observations with neighbors.");
		wxMessageDialog dlg (this, msg, "Success / Warning",
							 wxOK | wxICON_INFORMATION);
		dlg.ShowModal();
	} else {
		wxString msg("Rate calculation successful.");
		wxMessageDialog dlg (this, msg, "Success", wxOK | wxICON_INFORMATION);
		dlg.ShowModal();
	}
}