// ConstructLogs constructs logs structure for given parameters.
func ConstructLogs(podID string, rawLogs string, container string, logSelector *logs.LogViewSelector) *logs.Logs {
	logLines, firstLogLineReference, lastLogLineReference, logViewInfo := logs.ToLogLines(rawLogs).SelectLogs(logSelector)
	logs := &logs.Logs{
		PodId:                 podID,
		LogLines:              logLines,
		Container:             container,
		FirstLogLineReference: firstLogLineReference,
		LastLogLineReference:  lastLogLineReference,
		LogViewInfo:           logViewInfo,
	}
	return logs
}
func TestGetLogs(t *testing.T) {

	cases := []struct {
		info        string
		podId       string
		rawLogs     string
		container   string
		logSelector *logs.LogViewSelector
		expected    *logs.Logs
	}{
		{
			"return no logs if no logs are available",
			"",
			"",
			"",
			logs.AllLogViewSelector,
			&logs.Logs{
				PodId:     "",
				LogLines:  logs.ToLogLines(""),
				Container: "",
			},
		},
		{
			"return all logs if selected all logs",
			"pod-1",
			"1 log1\n2 log2\n3 log3\n4 log4\n5 log5",
			"test",
			logs.AllLogViewSelector,
			&logs.Logs{
				PodId:     "pod-1",
				LogLines:  logs.LogLines{"1 log1", "2 log2", "3 log3", "4 log4", "5 log5"},
				Container: "test",
				FirstLogLineReference: logs.LogLineId{
					LogTimestamp: "1",
					LineNum:      -1,
				},
				LastLogLineReference: logs.LogLineId{
					LogTimestamp: "5",
					LineNum:      1,
				},
				LogViewInfo: logs.LogViewInfo{
					ReferenceLogLineId: logs.LogLineId{
						LogTimestamp: "3",
						LineNum:      -1,
					},
					RelativeFrom: -2,
					RelativeTo:   3},
			},
		},
		{
			"return a slice relative to the first element",
			"pod-1",
			"1 log1\n2 log2\n3 log3\n4 log4\n5 log5",
			"test",
			&logs.LogViewSelector{
				ReferenceLogLineId: logs.OldestLogLineId,
				RelativeFrom:       1,
				RelativeTo:         3,
			},
			&logs.Logs{
				PodId:     "pod-1",
				LogLines:  logs.LogLines{"2 log2", "3 log3"},
				Container: "test",
				FirstLogLineReference: logs.LogLineId{
					LogTimestamp: "2",
					LineNum:      -1,
				},
				LastLogLineReference: logs.LogLineId{
					LogTimestamp: "3",
					LineNum:      -1,
				},
				LogViewInfo: logs.LogViewInfo{
					ReferenceLogLineId: logs.LogLineId{
						LogTimestamp: "3",
						LineNum:      -1,
					},
					RelativeFrom: -1,
					RelativeTo:   1},
			},
		},
		{
			"return a slice relative to the last element",
			"pod-1",
			"1 log1\n2 log2\n3 log3\n4 log4\n5 log5",
			"test",
			&logs.LogViewSelector{
				ReferenceLogLineId: logs.NewestLogLineId,
				RelativeFrom:       -3,
				RelativeTo:         -1,
			},
			&logs.Logs{
				PodId:     "pod-1",
				LogLines:  logs.LogLines{"2 log2", "3 log3"},
				Container: "test",
				FirstLogLineReference: logs.LogLineId{
					LogTimestamp: "2",
					LineNum:      -1,
				},
				LastLogLineReference: logs.LogLineId{
					LogTimestamp: "3",
					LineNum:      -1,
				},
				LogViewInfo: logs.LogViewInfo{
					ReferenceLogLineId: logs.LogLineId{
						LogTimestamp: "3",
						LineNum:      -1,
					},
					RelativeFrom: -1,
					RelativeTo:   1},
			},
		},
		{
			"return a slice relative to an arbitrary element",
			"pod-1",
			"1 log1\n2 log2\n3 log3\n4 log4\n5 log5",
			"test",
			&logs.LogViewSelector{
				ReferenceLogLineId: logs.LogLineId{
					LogTimestamp: logs.LogTimestamp("4"),
					LineNum:      1,
				},
				RelativeFrom: -2,
				RelativeTo:   0,
			},
			&logs.Logs{
				PodId:     "pod-1",
				LogLines:  logs.LogLines{"2 log2", "3 log3"},
				Container: "test",
				FirstLogLineReference: logs.LogLineId{
					LogTimestamp: "2",
					LineNum:      -1,
				},
				LastLogLineReference: logs.LogLineId{
					LogTimestamp: "3",
					LineNum:      -1,
				},
				LogViewInfo: logs.LogViewInfo{
					ReferenceLogLineId: logs.LogLineId{
						LogTimestamp: "3",
						LineNum:      -1,
					},
					RelativeFrom: -1,
					RelativeTo:   1},
			},
		},
		{
			"return a slice outside of log bounds - try to keep requested size",
			"pod-1",
			"1 log1\n2 log2\n3 log3\n4 log4\n5 log5",
			"test",
			&logs.LogViewSelector{
				ReferenceLogLineId: logs.LogLineId{
					LogTimestamp: logs.LogTimestamp("4"),
					LineNum:      1,
				},
				RelativeFrom: 1,
				RelativeTo:   3,
			},
			&logs.Logs{
				PodId:     "pod-1",
				LogLines:  logs.LogLines{"4 log4", "5 log5"},
				Container: "test",
				FirstLogLineReference: logs.LogLineId{
					LogTimestamp: "4",
					LineNum:      -1,
				},
				LastLogLineReference: logs.LogLineId{
					LogTimestamp: "5",
					LineNum:      1,
				},
				LogViewInfo: logs.LogViewInfo{
					ReferenceLogLineId: logs.LogLineId{
						LogTimestamp: "3",
						LineNum:      -1,
					},
					RelativeFrom: 1,
					RelativeTo:   3},
			},
		},
		{
			"return a slice outside of log bounds - try to keep requested size",
			"pod-1",
			"1 log1\n2 log2\n3 log3\n4 log4\n5 log5",
			"test",
			&logs.LogViewSelector{
				ReferenceLogLineId: logs.LogLineId{
					LogTimestamp: logs.LogTimestamp("4"),
					LineNum:      1,
				},
				RelativeFrom: -50,
				RelativeTo:   -48,
			},
			&logs.Logs{
				PodId:     "pod-1",
				LogLines:  logs.LogLines{"1 log1", "2 log2"},
				Container: "test",
				FirstLogLineReference: logs.LogLineId{
					LogTimestamp: "1",
					LineNum:      -1,
				},
				LastLogLineReference: logs.LogLineId{
					LogTimestamp: "2",
					LineNum:      -1,
				},
				LogViewInfo: logs.LogViewInfo{
					ReferenceLogLineId: logs.LogLineId{
						LogTimestamp: "3",
						LineNum:      -1,
					},
					RelativeFrom: -2,
					RelativeTo:   0},
			},
		},
		{
			"be able to handle duplicate timestamps",
			"pod-1",
			"1 log1\n1 log2\n1 log3\n1 log4\n1 log5",
			"test",
			&logs.LogViewSelector{
				ReferenceLogLineId: logs.LogLineId{
					LogTimestamp: logs.LogTimestamp("1"),
					LineNum:      2, // this means element with actual index 1.
				},
				RelativeFrom: 0,
				RelativeTo:   2, // request indices 1, 2
			},
			&logs.Logs{
				PodId:     "pod-1",
				LogLines:  logs.LogLines{"1 log2", "1 log3"},
				Container: "test",
				FirstLogLineReference: logs.LogLineId{
					LogTimestamp: "1",
					LineNum:      2,
				},
				LastLogLineReference: logs.LogLineId{
					LogTimestamp: "1",
					LineNum:      3,
				},
				LogViewInfo: logs.LogViewInfo{
					ReferenceLogLineId: logs.LogLineId{
						LogTimestamp: "1",
						LineNum:      3,
					},
					RelativeFrom: -1,
					RelativeTo:   1},
			},
		},
	}
	for _, c := range cases {
		actual := ConstructLogs(c.podId, c.rawLogs, c.container, c.logSelector)
		if !reflect.DeepEqual(actual, c.expected) {
			t.Errorf("Test Case: %s.\nReceived: %#v \nExpected: %#v\n\n", c.info, actual, c.expected)
		}
	}
}