func (widget *BoardWidget) UnmarshalJSON(data []byte) error {
	var widgetHandler struct {
		Definition *struct {
			Type *string `json:"type"`
		} `json:"definition"`
		Id     *int          `json:"id,omitempty"`
		Layout *WidgetLayout `json:"layout,omitempty"`
	}
	if err := json.Unmarshal(data, &widgetHandler); err != nil {
		return err
	}

	// Get the widget id
	widget.Id = widgetHandler.Id

	// Get the widget layout
	widget.Layout = widgetHandler.Layout

	// Get the widget definition based on the widget type
	switch *widgetHandler.Definition.Type {
	case ALERT_GRAPH_WIDGET:
		var alertGraphWidget struct {
			Definition AlertGraphDefinition `json:"definition"`
		}
		if err := json.Unmarshal(data, &alertGraphWidget); err != nil {
			return err
		}
		widget.Definition = alertGraphWidget.Definition
	case ALERT_VALUE_WIDGET:
		var alertValueWidget struct {
			Definition AlertValueDefinition `json:"definition"`
		}
		if err := json.Unmarshal(data, &alertValueWidget); err != nil {
			return err
		}
		widget.Definition = alertValueWidget.Definition
	case CHANGE_WIDGET:
		var changeWidget struct {
			Definition ChangeDefinition `json:"definition"`
		}
		if err := json.Unmarshal(data, &changeWidget); err != nil {
			return err
		}
		widget.Definition = changeWidget.Definition
	case CHECK_STATUS_WIDGET:
		var checkStatusWidget struct {
			Definition CheckStatusDefinition `json:"definition"`
		}
		if err := json.Unmarshal(data, &checkStatusWidget); err != nil {
			return err
		}
		widget.Definition = checkStatusWidget.Definition
	case DISTRIBUTION_WIDGET:
		var distributionWidget struct {
			Definition DistributionDefinition `json:"definition"`
		}
		if err := json.Unmarshal(data, &distributionWidget); err != nil {
			return err
		}
		widget.Definition = distributionWidget.Definition
	case EVENT_STREAM_WIDGET:
		var eventStreamWidget struct {
			Definition EventStreamDefinition `json:"definition"`
		}
		if err := json.Unmarshal(data, &eventStreamWidget); err != nil {
			return err
		}
		widget.Definition = eventStreamWidget.Definition
	case EVENT_TIMELINE_WIDGET:
		var eventTimelineWidget struct {
			Definition EventTimelineDefinition `json:"definition"`
		}
		if err := json.Unmarshal(data, &eventTimelineWidget); err != nil {
			return err
		}
		widget.Definition = eventTimelineWidget.Definition
	case FREE_TEXT_WIDGET:
		var freeTextWidget struct {
			Definition FreeTextDefinition `json:"definition"`
		}
		if err := json.Unmarshal(data, &freeTextWidget); err != nil {
			return err
		}
		widget.Definition = freeTextWidget.Definition
	case GROUP_WIDGET:
		var groupWidget struct {
			Definition GroupDefinition `json:"definition"`
		}
		if err := json.Unmarshal(data, &groupWidget); err != nil {
			return err
		}
		widget.Definition = groupWidget.Definition
	case HEATMAP_WIDGET:
		var heatmapWidget struct {
			Definition HeatmapDefinition `json:"definition"`
		}
		if err := json.Unmarshal(data, &heatmapWidget); err != nil {
			return err
		}
		widget.Definition = heatmapWidget.Definition
	case HOSTMAP_WIDGET:
		var hostmapWidget struct {
			Definition HostmapDefinition `json:"definition"`
		}
		if err := json.Unmarshal(data, &hostmapWidget); err != nil {
			return err
		}
		widget.Definition = hostmapWidget.Definition
	case IFRAME_WIDGET:
		var iframeWidget struct {
			Definition IframeDefinition `json:"definition"`
		}
		if err := json.Unmarshal(data, &iframeWidget); err != nil {
			return err
		}
		widget.Definition = iframeWidget.Definition
	case IMAGE_WIDGET:
		var imageWidget struct {
			Definition ImageDefinition `json:"definition"`
		}
		if err := json.Unmarshal(data, &imageWidget); err != nil {
			return err
		}
		widget.Definition = imageWidget.Definition
	case LOG_STREAM_WIDGET:
		var logStreamWidget struct {
			Definition LogStreamDefinition `json:"definition"`
		}
		if err := json.Unmarshal(data, &logStreamWidget); err != nil {
			return err
		}
		widget.Definition = logStreamWidget.Definition
	case MANAGE_STATUS_WIDGET:
		var manageStatusWidget struct {
			Definition ManageStatusDefinition `json:"definition"`
		}
		if err := json.Unmarshal(data, &manageStatusWidget); err != nil {
			return err
		}
		widget.Definition = manageStatusWidget.Definition
	case NOTE_WIDGET:
		var noteWidget struct {
			Definition NoteDefinition `json:"definition"`
		}
		if err := json.Unmarshal(data, &noteWidget); err != nil {
			return err
		}
		widget.Definition = noteWidget.Definition
	case QUERY_VALUE_WIDGET:
		var queryValueWidget struct {
			Definition QueryValueDefinition `json:"definition"`
		}
		if err := json.Unmarshal(data, &queryValueWidget); err != nil {
			return err
		}
		widget.Definition = queryValueWidget.Definition
	case SCATTERPLOT_WIDGET:
		var scatterplotWidget struct {
			Definition ScatterplotDefinition `json:"definition"`
		}
		if err := json.Unmarshal(data, &scatterplotWidget); err != nil {
			return err
		}
		widget.Definition = scatterplotWidget.Definition
	case TIMESERIES_WIDGET:
		var timeseriesWidget struct {
			Definition TimeseriesDefinition `json:"definition"`
		}
		if err := json.Unmarshal(data, &timeseriesWidget); err != nil {
			return err
		}
		widget.Definition = timeseriesWidget.Definition
	case TOPLIST_WIDGET:
		var toplistWidget struct {
			Definition ToplistDefinition `json:"definition"`
		}
		if err := json.Unmarshal(data, &toplistWidget); err != nil {
			return err
		}
		widget.Definition = toplistWidget.Definition
	case TRACE_SERVICE_WIDGET:
		var traceServiceWidget struct {
			Definition TraceServiceDefinition `json:"definition"`
		}
		if err := json.Unmarshal(data, &traceServiceWidget); err != nil {
			return err
		}
		widget.Definition = traceServiceWidget.Definition
	default:
		return fmt.Errorf("Cannot unmarshal widget of type: %s", *widgetHandler.Definition.Type)
	}

	return nil
}
func (widget *BoardWidget) UnmarshalJSON(data []byte) error {
	var widgetHandler struct {
		Definition *struct {
			Type *string `json:"type"`
		} `json:"definition"`
		Id     *int          `json:"id,omitempty"`
		Layout *WidgetLayout `json:"layout,omitempty"`
	}
	if err := json.Unmarshal(data, &widgetHandler); err != nil {
		return err
	}

	// Get the widget id
	widget.Id = widgetHandler.Id

	// Get the widget layout
	widget.Layout = widgetHandler.Layout

	// Get the widget definition based on the widget type
	switch *widgetHandler.Definition.Type {
	case ALERT_GRAPH_WIDGET:
		var alertGraphWidget struct {
			Definition AlertGraphDefinition `json:"definition"`
		}
		if err := json.Unmarshal(data, &alertGraphWidget); err != nil {
			return err
		}
		widget.Definition = alertGraphWidget.Definition
	case ALERT_VALUE_WIDGET:
		var alertValueWidget struct {
			Definition AlertValueDefinition `json:"definition"`
		}
		if err := json.Unmarshal(data, &alertValueWidget); err != nil {
			return err
		}
		widget.Definition = alertValueWidget.Definition
	case CHANGE_WIDGET:
		var changeWidget struct {
			Definition ChangeDefinition `json:"definition"`
		}
		if err := json.Unmarshal(data, &changeWidget); err != nil {
			return err
		}
		widget.Definition = changeWidget.Definition
	case CHECK_STATUS_WIDGET:
		var checkStatusWidget struct {
			Definition CheckStatusDefinition `json:"definition"`
		}
		if err := json.Unmarshal(data, &checkStatusWidget); err != nil {
			return err
		}
		widget.Definition = checkStatusWidget.Definition
	case DISTRIBUTION_WIDGET:
		var distributionWidget struct {
			Definition DistributionDefinition `json:"definition"`
		}
		if err := json.Unmarshal(data, &distributionWidget); err != nil {
			return err
		}
		widget.Definition = distributionWidget.Definition
	case EVENT_STREAM_WIDGET:
		var eventStreamWidget struct {
			Definition EventStreamDefinition `json:"definition"`
		}
		if err := json.Unmarshal(data, &eventStreamWidget); err != nil {
			return err
		}
		widget.Definition = eventStreamWidget.Definition
	case EVENT_TIMELINE_WIDGET:
		var eventTimelineWidget struct {
			Definition EventTimelineDefinition `json:"definition"`
		}
		if err := json.Unmarshal(data, &eventTimelineWidget); err != nil {
			return err
		}
		widget.Definition = eventTimelineWidget.Definition
	case FREE_TEXT_WIDGET:
		var freeTextWidget struct {
			Definition FreeTextDefinition `json:"definition"`
		}
		if err := json.Unmarshal(data, &freeTextWidget); err != nil {
			return err
		}
		widget.Definition = freeTextWidget.Definition
	case GROUP_WIDGET:
		var groupWidget struct {
			Definition GroupDefinition `json:"definition"`
		}
		if err := json.Unmarshal(data, &groupWidget); err != nil {
			return err
		}
		widget.Definition = groupWidget.Definition
	case HEATMAP_WIDGET:
		var heatmapWidget struct {
			Definition HeatmapDefinition `json:"definition"`
		}
		if err := json.Unmarshal(data, &heatmapWidget); err != nil {
			return err
		}
		widget.Definition = heatmapWidget.Definition
	case HOSTMAP_WIDGET:
		var hostmapWidget struct {
			Definition HostmapDefinition `json:"definition"`
		}
		if err := json.Unmarshal(data, &hostmapWidget); err != nil {
			return err
		}
		widget.Definition = hostmapWidget.Definition
	case IFRAME_WIDGET:
		var iframeWidget struct {
			Definition IframeDefinition `json:"definition"`
		}
		if err := json.Unmarshal(data, &iframeWidget); err != nil {
			return err
		}
		widget.Definition = iframeWidget.Definition
	case IMAGE_WIDGET:
		var imageWidget struct {
			Definition ImageDefinition `json:"definition"`
		}
		if err := json.Unmarshal(data, &imageWidget); err != nil {
			return err
		}
		widget.Definition = imageWidget.Definition
	case LOG_STREAM_WIDGET:
		var logStreamWidget struct {
			Definition LogStreamDefinition `json:"definition"`
		}
		if err := json.Unmarshal(data, &logStreamWidget); err != nil {
			return err
		}
		widget.Definition = logStreamWidget.Definition
	case MANAGE_STATUS_WIDGET:
		var manageStatusWidget struct {
			Definition ManageStatusDefinition `json:"definition"`
		}
		if err := json.Unmarshal(data, &manageStatusWidget); err != nil {
			return err
		}
		widget.Definition = manageStatusWidget.Definition
	case NOTE_WIDGET:
		var noteWidget struct {
			Definition NoteDefinition `json:"definition"`
		}
		if err := json.Unmarshal(data, &noteWidget); err != nil {
			return err
		}
		widget.Definition = noteWidget.Definition
	case QUERY_VALUE_WIDGET:
		var queryValueWidget struct {
			Definition QueryValueDefinition `json:"definition"`
		}
		if err := json.Unmarshal(data, &queryValueWidget); err != nil {
			return err
		}
		widget.Definition = queryValueWidget.Definition
	case SCATTERPLOT_WIDGET:
		var scatterplotWidget struct {
			Definition ScatterplotDefinition `json:"definition"`
		}
		if err := json.Unmarshal(data, &scatterplotWidget); err != nil {
			return err
		}
		widget.Definition = scatterplotWidget.Definition
	case TIMESERIES_WIDGET:
		var timeseriesWidget struct {
			Definition TimeseriesDefinition `json:"definition"`
		}
		if err := json.Unmarshal(data, &timeseriesWidget); err != nil {
			return err
		}
		widget.Definition = timeseriesWidget.Definition
	case TOPLIST_WIDGET:
		var toplistWidget struct {
			Definition ToplistDefinition `json:"definition"`
		}
		if err := json.Unmarshal(data, &toplistWidget); err != nil {
			return err
		}
		widget.Definition = toplistWidget.Definition
	case TRACE_SERVICE_WIDGET:
		var traceServiceWidget struct {
			Definition TraceServiceDefinition `json:"definition"`
		}
		if err := json.Unmarshal(data, &traceServiceWidget); err != nil {
			return err
		}
		widget.Definition = traceServiceWidget.Definition
	default:
		return fmt.Errorf("Cannot unmarshal widget of type: %s", *widgetHandler.Definition.Type)
	}

	return nil
}
// UnmarshalJSON is a Custom Unmarshal for BoardWidget. If first tries to unmarshal the data in a light
// struct that allows to get the widget type. Then based on the widget type, it will try to unmarshal the
// data using the corresponding widget struct.