package common_test

import (
	"encoding/hex"
	"encoding/json"
	"fmt"
	"strings"
	"testing"
	"time"

	"github.com/fiskerinc/cloud-services/pkg/common"
	"github.com/fiskerinc/cloud-services/pkg/common/dbbasemodel"
	th "github.com/fiskerinc/cloud-services/pkg/testhelper"
	v "github.com/fiskerinc/cloud-services/pkg/utils/vod"
	"github.com/fiskerinc/cloud-services/pkg/utils/elptr"
)

func TestUpdatePackageManifest(t *testing.T) {
	manifestValues := map[string]interface{}{
		"ID":           int64(10000),
		"Name":         "<package_name>",
		"Description":  "<description>",
		"Version":      "<version>",
		"ReleaseNotes": "http://releasenotes.com/TEST",
		"Fingerprint":  "<fingerprint>",
	}
	ecuValues := map[string]interface{}{
		"ECU":               "<ecu name>",
		"Version":           "<ecu_version>",
		"HWVersion":         "<hardware version>",
		"ConfigurationMask": "<configuration_mask>",
	}
	fileValues := map[string]interface{}{
		"FileID":   "<file id>",
		"URL":      "<ecu_download_url>",
		"FileSize": uint64(11111),
		"Checksum": "<ecu checksum>",
		"FileType": "none",
	}
	writeRegionValues := map[string]interface{}{
		"Offset": uint64(100),
		"Length": uint64(101),
	}
	eraseRegionValues := map[string]interface{}{
		"Offset": uint64(200),
		"Length": uint64(201),
	}
	data := `{
		"id": 10000,
		"name": "<package_name>",
		"version": "<version>",
		"description": "<description>",
		"release_notes": "http://releasenotes.com/TEST",
		"fingerprint": "<fingerprint>",
		"ecu_updates": [
			{
				"name": "<ecu name>",
				"version": "<ecu_version>",
				"hw_version": "<hardware version>",
				"configuration_mask": "<configuration_mask>",
				"files": [
					{
            "file_id": "<file id>",
						"version": "<file version>",
						"url": "<ecu_download_url>",
						"file_size": 11111,
						"write_region": {
							"offset": 100,
							"length": 101
						},
						"erase_region": {
							"offset": 200,
							"length": 201
						},
						"checksum": "<ecu checksum>",
						"type": "none"
					}
				]
			}
		]
	}`

	result := common.UpdateManifest{}

	err := json.Unmarshal([]byte(data), &result)
	if err != nil {
		t.Error(err)
	}

	th.PropsTester(t, &result, manifestValues)

	if len(result.ECUs) != 1 {
		t.Errorf(th.TestErrorTemplate, "ECUs", 1, len(result.ECUs))
	} else {
		ecu := result.ECUs[0]
		th.PropsTester(t, ecu, ecuValues)
		if len(ecu.Files) != 1 {
			t.Errorf(th.TestErrorTemplate, "Files", 1, len(ecu.Files))
		} else {
			file := ecu.Files[0]
			th.PropsTester(t, file, fileValues)
			th.PropsTester(t, file.WriteRegion, writeRegionValues)
			if file.EraseRegion != nil {
				th.PropsTester(t, file.EraseRegion, eraseRegionValues)
			} else {
				t.Errorf(th.TestErrorTemplate, "EraseRegion", "not nil", file.EraseRegion)
			}
		}
	}
}

func TestCopyManifest(t *testing.T) {
	manifestA := common.UpdateManifest{
		ID:   100,
		Name: "TEST A",
		ECUs: []*common.UpdateManifestECU{
			{
				ECU:          "ICC",
				SelfDownload: true,
				Files: []*common.UpdateManifestFile{
					{
						FileID:   "FILEID",
						URL:      "http://download.com/test.bin",
						FileSize: 50,
						FileType: "software",
						WriteRegion: common.MemoryRegion{
							Offset: 100,
							Length: 101,
						},
					},
				},
			},
			{ECU: "ADAS"},
			{ECU: "ECC"},
		},
	}
	manifestB := manifestA.Copy()

	if manifestA.ID != manifestB.ID {
		t.Errorf(th.TestErrorTemplate, "Manifest ID", manifestA.ID, manifestB.ID)
	}

	if manifestA.Name != manifestB.Name {
		t.Errorf(th.TestErrorTemplate, "Manifest Name", manifestA.ID, manifestB.ID)
	}

	if len(manifestA.ECUs) != len(manifestB.ECUs) {
		t.Errorf(th.TestErrorTemplate, "ECUs count", len(manifestA.ECUs), len(manifestB.ECUs))
	} else {
		if manifestB.ECUs[0].ECU != "ICC" {
			t.Errorf(th.TestErrorTemplate, "ECUs[0] Name", "ICC", manifestB.ECUs[0].ECU)
		} else {
			if len(manifestB.ECUs[0].Files) != 1 {
				t.Errorf(th.TestErrorTemplate, "ECUs[0].Files count", 1, len(manifestB.ECUs[0].Files))
			} else {
				if manifestB.ECUs[0].Files[0].WriteRegion.Offset != 100 {
					t.Errorf(th.TestErrorTemplate, "ECUs[0].Files[0].WriteRegion", 100, manifestB.ECUs[0].Files[0].WriteRegion.Offset)
				}
			}
		}
	}

	manifestB.Name = "TEST B"
	if manifestA.Name == "TEST B" {
		t.Errorf(th.TestErrorTemplate, "Manifest Name Changes", "TEST A", manifestA.Name)
	}

	manifestB = manifestA.Copy()
	manifestB.SortECUs()
	if len(manifestB.ECUs) != 3 {
		t.Errorf(th.TestErrorTemplate, "Manifest Copy count", 3, len(manifestB.ECUs))
	}

	if len(manifestA.ECUs) != 3 {
		t.Errorf(th.TestErrorTemplate, "Manifest ECU count", 3, len(manifestA.ECUs))
	}
}

func TestUpdateManifestScrub(t *testing.T) {
	expected := `{"ecu_updates":[{"name":"TREX","version":"0.0.1","hw_version":"0.0.2"},{"name":"ECU","version":"A-VERS","hw_version":"A-VERS","configuration_mask":"AAAAAAAA","files":[{"file_id":"FILEID","url":"URL","checksum":"aaaaaaaa","type":"calibration","write_region":{"offset":101,"length":102},"erase_region":{"offset":201,"length":202}}],"rollback":[{"version":"VERSIONOLD","files":[{"file_id":"FILEIDOLD","url":"URLOLD","checksum":"bbbbbbbb","type":"software","write_region":{"offset":301,"length":302},"erase_region":{"offset":401,"length":402}}]}]},{"name":"D","version":"D-VERS","hw_version":"D-VERS","configuration_mask":"AAAAAAAA"},{"name":"OBC","version":"PDU-VERS","hw_version":"PDU-VERS","configuration_mask":"AAAAAAAA"},{"name":"ICC","version":"ICC-VERS","hw_version":"ICC-VERS","configuration_mask":"AAAAAAAA","self_download":true}],"rollback":true,"type":"standard","vod":"VOD","update_duration":30}`
	now := time.Now()
	manifest := common.UpdateManifest{
		Name:            "TEST",
		Description:     "DESCRIPTION",
		ReleaseNotes:    "RELEASENOTES",
		ECUList:         "ECULIST",
		RollbackEnabled: true,
		Type:            "standard",
		VOD:             "VOD",
		Country:         "US",
		PowerTrain:      "MD23",
		Restraint:       "None",
		Model:           "Ocean",
		Trim:            "Sport",
		Year:            2022,
		BodyType:        "truck",
		ECUs: []*common.UpdateManifestECU{
			{
				ID:                100,
				UpdateManifestID:  200,
				ECU:               "PDU",
				Version:           "PDU-VERS",
				HWVersions:        []string{"PDU-VERS"},
				Mode:              "PDU",
				ConfigurationMask: "AAAAAAAA",
				InstallPriority:   4,
			},
			{
				ID:                100,
				UpdateManifestID:  200,
				ECU:               "D",
				Version:           "D-VERS",
				HWVersions:        []string{"D-VERS"},
				Mode:              "D",
				ConfigurationMask: "AAAAAAAA",
				InstallPriority:   3,
			},
			{
				ID:               100,
				UpdateManifestID: 200,
				ECU:              "TREX",
				Version:          "0.0.1",
				HWVersions:       []string{"0.0.2"},
				Mode:             "D",
				InstallPriority:  1,
			},
			{
				ID:                100,
				UpdateManifestID:  200,
				ECU:               "ICC",
				Version:           "ICC-VERS",
				HWVersions:        []string{"ICC-VERS"},
				Mode:              "ICC",
				ConfigurationMask: "AAAAAAAA",
				SelfDownload:      true,
				InstallPriority:   5,
				Files: []*common.UpdateManifestFile{
					{
						FileID:              "ICCFILEID",
						UpdateManifestECUID: 100,
						Filename:            "ICCFILENAME",
						URL:                 "URL",
						FileType:            common.Calibration,
						Checksum:            "aaaaaaaa",
						WriteRegionID:       100,
						WriteRegion: common.MemoryRegion{
							Offset: 101,
							Length: 102,
						},
						EraseRegionID: 200,
						EraseRegion: &common.MemoryRegion{
							Offset: 201,
							Length: 202,
						},
						DBModelBase: dbbasemodel.DBModelBase{
							CreatedAt: &now,
							UpdatedAt: &now,
						},
					},
				},
			},
			{
				ID:                100,
				UpdateManifestID:  200,
				ECU:               "ECU",
				Version:           "A-VERS",
				HWVersions:        []string{"A-VERS"},
				Mode:              "A",
				ConfigurationMask: "AAAAAAAA",
				InstallPriority:   2,
				Files: []*common.UpdateManifestFile{
					{
						FileID:              "FILEID",
						UpdateManifestECUID: 100,
						Filename:            "FILENAME",
						URL:                 "URL",
						FileType:            common.Calibration,
						Checksum:            "aaaaaaaa",
						WriteRegionID:       100,
						WriteRegion: common.MemoryRegion{
							Offset: 101,
							Length: 102,
						},
						EraseRegionID: 200,
						EraseRegion: &common.MemoryRegion{
							Offset: 201,
							Length: 202,
						},
						DBModelBase: dbbasemodel.DBModelBase{
							CreatedAt: &now,
							UpdatedAt: &now,
						},
					},
				},
				Rollback: []*common.UpdateManifestECU{
					{
						ID:               100,
						UpdateManifestID: 200,
						ECU:              "ECU",
						Version:          "VERSIONOLD",
						Mode:             "A",
						DBModelBase: dbbasemodel.DBModelBase{
							CreatedAt: &now,
							UpdatedAt: &now,
						},
						Files: []*common.UpdateManifestFile{
							{
								FileID:              "FILEIDOLD",
								UpdateManifestECUID: 1001,
								Filename:            "FILENAMEOLD",
								URL:                 "URLOLD",
								FileType:            common.Software,
								Checksum:            "bbbbbbbb",
								WriteRegionID:       300,
								WriteRegion: common.MemoryRegion{
									Offset: 301,
									Length: 302,
								},
								EraseRegionID: 400,
								EraseRegion: &common.MemoryRegion{
									Offset: 401,
									Length: 402,
								},
								DBModelBase: dbbasemodel.DBModelBase{
									CreatedAt: &now,
									UpdatedAt: &now,
								},
							},
						},
					},
				},
				DBModelBase: dbbasemodel.DBModelBase{
					CreatedAt: &now,
					UpdatedAt: &now,
				},
			},
		},
		DBModelBase: dbbasemodel.DBModelBase{
			CreatedAt: &now,
			UpdatedAt: &now,
		},
	}

	manifest.SortECUs()
	manifest.Scrub(common.TRex)
	data, err := json.Marshal(manifest)
	if err != nil {
		t.Error(err)
	}

	if string(data) != expected {
		t.Errorf(th.TestErrorTemplate, "Scrub", expected, string(data))
	}
}

func TestSortECUs(t *testing.T) {
	// Because of the stringify function on updateManifest, we set the name of the ecu as a number
	manifest := common.UpdateManifest{
		ECUs: []*common.UpdateManifestECU{
			{
				ECU:             "3",
				Mode:            "ICC",
				Version:         "ICC_VER",
				HWVersion:       "ICC_VER",
				SelfDownload:    true,
				InstallPriority: 3,
			},
			{
				ECU:             "2",
				Mode:            "A",
				Version:         "A_VER",
				HWVersion:       "A_VER",
				InstallPriority: 4,
			},
			{
				ECU:             "4",
				Mode:            "A",
				Version:         "A_VER",
				HWVersion:       "A_VER",
				InstallPriority: 2,
			},
			{
				ECU:             "5",
				Mode:            "PDU",
				Version:         "PDU_VER",
				HWVersion:       "PDU_VER",
				InstallPriority: 1,
			},
			{
				ECU:             "1",
				Mode:            "D",
				Version:         "D_VER",
				HWVersion:       "D_VER",
				InstallPriority: 5,
			},
		},
	}

	manifest.SortECUs()
	expected := "[UpdateManifestECU<5 PDU_VER []> UpdateManifestECU<4 A_VER []> UpdateManifestECU<3 ICC_VER []> UpdateManifestECU<2 A_VER []> UpdateManifestECU<1 D_VER []>]"
	result := fmt.Sprint(manifest.ECUs)
	if result != expected {
		t.Errorf(th.TestErrorTemplate, "SortECUs", expected, result)
	}
}

func TestGenerateFingerprint(t *testing.T) {
	s, date := "00000000000000000", time.Date(2022, 10, 20, 0, 0, 0, 0, time.UTC)
	expected := "221020FISKER00000000000000000"
	m := common.UpdateManifest{}

	m.GenerateFingerprint(date, s)

	if m.Fingerprint != expected {
		t.Errorf(th.TestErrorTemplate, "GenerateFingerprint normal", expected, m.Fingerprint)
	}

	s += "0"

	m.GenerateFingerprint(date, s)

	if m.Fingerprint != expected {
		t.Errorf(th.TestErrorTemplate, "GenerateFingerprint with concat", expected, m.Fingerprint)
	}
}

func TestUpdateManifestECUFileSort(t *testing.T) {
	ptrBool := true
	type testcase struct {
		name     string
		ecu      common.UpdateManifestECU
		expected string
	}
	tests := []testcase{
		{
			name:     "file order",
			expected: `{"version":"","files":[{"file_id":"file2","url":"","type":"calibration","write_region":{"offset":0,"length":0}},{"file_id":"file2","url":"","type":"software","order":1,"write_region":{"offset":0,"length":0}},{"file_id":"file3","url":"","type":"bootloader","order":2,"write_region":{"offset":0,"length":0}}]}`,
			ecu: common.UpdateManifestECU{
				Files: []*common.UpdateManifestFile{
					{
						FileID:    "file3",
						FileOrder: 2,
						FileType:  common.Bootloader,
					},
					{
						FileID:    "file2",
						FileOrder: 1,
						FileType:  common.Software,
					},
					{
						FileID:    "file2",
						FileOrder: 0,
						FileType:  common.Calibration,
					},
				},
			},
		},
		{
			name:     "file type",
			expected: `{"version":"","files":[{"file_id":"file1","url":"","type":"bootloader","write_region":{"offset":0,"length":0}},{"file_id":"file2","url":"","type":"software","write_region":{"offset":0,"length":0}},{"file_id":"file3","url":"","type":"calibration","write_region":{"offset":0,"length":0}},{"file_id":"file4","url":"","type":"other","write_region":{"offset":0,"length":0}}]}`,
			ecu: common.UpdateManifestECU{
				Files: []*common.UpdateManifestFile{
					{
						FileID:    "file4",
						FileOrder: 0,
						FileType:  common.Other,
					},
					{
						FileID:    "file3",
						FileOrder: 0,
						FileType:  common.Calibration,
					},
					{
						FileID:    "file1",
						FileOrder: 0,
						FileType:  common.Bootloader,
					},
					{
						FileID:    "file2",
						FileOrder: 0,
						FileType:  common.Software,
					},
				},
			},
		},
		{
			name:     "file type w/ override bootloader last",
			expected: `{"version":"","files":[{"file_id":"file2","url":"","type":"software","write_region":{"offset":0,"length":0}},{"file_id":"file3","url":"","type":"calibration","write_region":{"offset":0,"length":0}},{"file_id":"file4","url":"","type":"other","write_region":{"offset":0,"length":0}},{"file_id":"file1","url":"","type":"bootloader","order":1,"write_region":{"offset":0,"length":0}}]}`,
			ecu: common.UpdateManifestECU{
				Files: []*common.UpdateManifestFile{
					{
						FileID:    "file4",
						FileOrder: 0,
						FileType:  common.Other,
					},
					{
						FileID:    "file3",
						FileOrder: 0,
						FileType:  common.Calibration,
					},
					{
						FileID:    "file1",
						FileOrder: 1,
						FileType:  common.Bootloader,
					},
					{
						FileID:    "file2",
						FileOrder: 0,
						FileType:  common.Software,
					},
				},
			},
		},
		{
			name:     "signature sort parsed files",
			expected: `{"version":"","files":[{"file_id":"file0","filename":"bootloader.bin","url":"","checksum":"CHECKSUM","type":"bootloader","write_region":{"offset":0,"length":0}},{"file_id":"file1","filename":"MAGNA_BCM_FBL_driver.s19_1.bin","url":"","type":"software","order":1,"write_region":{"offset":0,"length":0},"parsed_file":true},{"file_id":"file2","filename":"MAGNA_BCM_FBL_driver.s19_2.bin","url":"","type":"software","order":2,"write_region":{"offset":0,"length":0},"parsed_file":true},{"file_id":"file3","filename":"MAGNA_BCM_FBL_driver.s19_3.bin","url":"","type":"software","order":3,"write_region":{"offset":0,"length":0},"parsed_file":true},{"file_id":"file4","filename":"MAGNA_BCM_FBL_driver.s19_4.bin","url":"","type":"software","order":4,"write_region":{"offset":0,"length":0},"parsed_file":true,"signature":"SIGNATURE"},{"file_id":"file5","filename":"calibration","url":"","type":"calibration","write_region":{"offset":0,"length":0}}]}`,
			ecu: common.UpdateManifestECU{
				Files: []*common.UpdateManifestFile{
					{
						FileID:    "file5",
						Filename:  "calibration",
						FileOrder: 0,
						FileType:  common.Calibration,
					},
					{
						FileID:    "file4",
						Filename:  "MAGNA_BCM_FBL_driver.s19_4.bin",
						FileOrder: 0,
						FileType:  common.Software,
						Parsed:    &ptrBool,
						Checksum:  "SHOULD NOT BE SENT",
						Signature: "SIGNATURE",
					},
					{
						FileID:    "file3",
						Filename:  "MAGNA_BCM_FBL_driver.s19_3.bin",
						FileOrder: 0,
						FileType:  common.Software,
						Parsed:    &ptrBool,
						Checksum:  "SHOULD NOT BE SENT",
						Signature: "SHOULD NOT BE SENT",
					},
					{
						FileID:    "file1",
						Filename:  "MAGNA_BCM_FBL_driver.s19_1.bin",
						FileOrder: 1,
						FileType:  common.Software,
						Parsed:    &ptrBool,
						Checksum:  "SHOULD NOT BE SENT",
						Signature: "SHOULD NOT BE SENT",
					},
					{
						FileID:    "file2",
						Filename:  "MAGNA_BCM_FBL_driver.s19_2.bin",
						FileOrder: 0,
						FileType:  common.Software,
						Parsed:    &ptrBool,
						Checksum:  "SHOULD NOT BE SENT",
						Signature: "SHOULD NOT BE SENT",
					},
					{
						FileID:    "file0",
						Filename:  "bootloader.bin",
						FileOrder: 0,
						FileType:  common.Bootloader,
						Checksum:  "CHECKSUM",
					},
				},
			},
		},
	}

	for _, test := range tests {
		t.Run(test.name, func(t *testing.T) {
			test.ecu.SortFiles()
			test.ecu.ImageSignatureChecksumCheck()
			data, err := json.Marshal(test.ecu)
			if err != nil {
				t.Error(err)
				return
			}
			if string(data) != test.expected {
				t.Errorf(th.TestErrorTemplate, test.name, test.expected, string(data))
			}
		})
	}
}

func TestImageSignatureChecksumCheckParsedFiles(t *testing.T) {
	type testcase struct {
		name     string
		ecu      common.UpdateManifestECU
		expected string
	}

	tests := []testcase{
		{
			name:     "parsedFilesTest",
			expected: `{"version":"","files":[{"file_id":"","filename":"VSP.hex_0.bin","url":"","write_region":{"offset":0,"length":0},"parsed_file":true},{"file_id":"","filename":"VSP.hex_1.bin","url":"","order":1,"write_region":{"offset":0,"length":0},"parsed_file":true},{"file_id":"","filename":"VSP.hex_2.bin","url":"","order":2,"write_region":{"offset":0,"length":0},"parsed_file":true,"signature":"showMe"}]}`,
			ecu: common.UpdateManifestECU{
				Files: []*common.UpdateManifestFile{
					{
						Filename:  "VSP.hex_2.bin",
						Parsed:    elptr.ElPtr(true),
						Checksum:  "dontshow",
						Signature: "showMe",
					},
					{
						Filename:  "VSP.hex_0.bin",
						Parsed:    elptr.ElPtr(true),
						Checksum:  "dontshow",
						Signature: "dontshow",
					},
					{
						Filename:  "VSP.hex_1.bin",
						Parsed:    elptr.ElPtr(true),
						Checksum:  "dontshow",
						Signature: "dontshow",
					},
				},
			},
		},
	}

	for _, test := range tests {
		t.Run(test.name, func(t *testing.T) {
			err := test.ecu.ImageSignatureChecksumCheck()
			if err != nil {
				t.Error(err)
				return
			}
			data, err := json.Marshal(test.ecu)
			if err != nil {
				t.Error(err)
				return
			}
			if string(data) != test.expected {
				t.Errorf(th.TestErrorTemplate, test.name, test.expected, string(data))
			}
		})
	}
}

func TestRemoveParsedS19HexFiles(t *testing.T) {
	mani := common.UpdateManifest{
		ECUs: []*common.UpdateManifestECU{
			{
				Files: []*common.UpdateManifestFile{
					{
						Parsed: elptr.ElPtr(true),
					},
					{
						Parsed: elptr.ElPtr(false),
					},
					{
						Parsed: nil,
					},
				},
			},
			/* 			&common.UpdateManifestECU{
				Files:             []*common.UpdateManifestFile{},
			}, */
		},
	}

	mani.RemoveParsedS19HexFiles()
	files := mani.ECUs[0].Files
	if len(files) != 2 {
		t.Logf("Received wrong number of results, expected 2 got : %d\n", len(files))
		t.Fail()
	}
	for _, file := range files {

		if file.Parsed != nil && *file.Parsed {
			t.Log(*file.Parsed)
			t.Log("Found a file that was parsed")
			t.Fail()
		}
	}

}

func TestCopyFunction(t *testing.T) {
	um := common.UpdateManifest{
		ID:      1,
		Name:    "Update Manifest",
		Version: "New Version",
		ECUs: []*common.UpdateManifestECU{{
			ID:               1,
			UpdateManifestID: 1,
			ECU:              "Test",
			Files: []*common.UpdateManifestFile{
				{
					FileID:   "0",
					Filename: "0",
					Parsed:   elptr.ElPtr(true),
				},
				{
					FileID:   "1",
					Filename: "1",
					Parsed:   elptr.ElPtr(true),
				},
				{
					FileID:   "2",
					Filename: "2",
					Parsed:   elptr.ElPtr(false),
				},
				{
					FileID:   "3",
					Filename: "3",
					Parsed:   elptr.ElPtr(true),
				},
			},
		}},
	}

	umCopy := um.Copy()
	umCopy.RemoveOriginalS19HexFiles()

	umIds := filesToIDArray(um.ECUs[0].Files)
	if len(umIds) != 4 || umIds[0] != "0" || umIds[1] != "1" || umIds[2] != "2" || umIds[3] != "3" {
		t.Log("Failed, original um files modified")
		t.Log(umIds)
		t.Fail()
	}
	umCopyIds := filesToIDArray(umCopy.ECUs[0].Files)
	if len(umCopyIds) != 3 || umCopyIds[0] != "0" || umCopyIds[1] != "1" || umCopyIds[2] != "3" {
		t.Log("Failed, original umCopy files modified wrong")
		t.Log(umCopyIds)
		t.Fail()
	}
}

func filesToIDArray(files []*common.UpdateManifestFile) []string {
	idArray := make([]string, 0, len(files))
	for _, x := range files {
		idArray = append(idArray, x.FileID)
	}
	return idArray
}

func TestAddSumsToVOD(t *testing.T) {
	var um common.UpdateManifest
	um.ID = 9686
	um.SUMS = "2013.05.01.02.E"
	um.VOD = "00A92301084000000101012200010101010001010101000000000000000000FF7EFF7F000101010101000101010100010001010101000101010100000000000000000000000000010101000100000100010101000201010101000101020101000101010200010101010101010101000101000100010001010101010101010101010000000000000100000101020101010101010000000000000000FFFFFF00000002010102020001015F"
	um.AddSUMSToVOD()
	if um.VOD != "01012301084000000101012200010101010001010101000000000000000000ff7eff7f000101010101000101010100010001010101000101010100000000000000000000000000010101000100000100010101000201010101000101020101000101010200010101010101010101000101000100010001010101010101010101010000000000000100000101020101010101010000000000000000ffffff00000002010102020001010000000000000000000000000000000000000000000000000000000000000096862013050102010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000038" {
		t.Fail()
	}
	// 255 For actual data, 2 for length, 1 for crc * 2
	if len(um.VOD) != 516 {
		t.Logf("Generated VOD of wrong length: %d\n", len(um.VOD))
	}
}

func TestVODVersionAdder(t *testing.T) {
	var um common.UpdateManifest
	// expected := "00a62299027600000101012200010100010001010101000000000000000000fffeffff000101010101010101010100010001010101000101010100000000000000000000000000010101000100000100010101000201010101000101020101000101010200010101010101010101000101010100010001010101010101010201010000000000000100000101ff00000001010200000000000003ffffffff0000000201010200000100000000000000000000000000000000000000000000000000000000000000009686201305010201000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
	expected := "01012301084000000101012200010101010001010101000000000000000000ff7eff7f000101010101000101010100010001010101000101010100000000000000000000000000010101000100000100010101000201010101000101020101000101010200010101010101010101000101000100010001010101010101010101010000000000000100000101020101010101010000000000000000ffffff00000002010102020001010000000000000000000000000000000000000000000000000000000000000096862013050102010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000038"
	//"01002301084000000101012200010101010001010101000000000000000000ff7eff7f000101010101000101010100010001010101000101010100000000000000000000000000010101000100000100010101000201010101000101020101000101010200010101010101010101000101000100010001010101010101010101010000000000000100000101020101010101010000000000000000ffffff0000000201010202000101000000000000000000000000000000000000000000000000000000000000009686201305010201000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000036"
	um.ID = 9686
	um.SUMS = "2013.05.01.02.E"
	// Alex's
	// startVOD := "00A92301084000000101012200010101010001010101000000000000000000FF7EFF7F000101010101000101010100010001010101000101010100000000000000000000000000010101000100000100010101000201010101000101020101000101010200010101010101010101000101000100010001010101010101010101010000000000000100000101020101010101010000000000000000FFFFFF000000020101020200010100"
	startVOD := "00A92301084000000101012200010101010001010101000000000000000000FF7EFF7F000101010101000101010100010001010101000101010100000000000000000000000000010101000100000100010101000201010101000101020101000101010200010101010101010101000101000100010001010101010101010101010000000000000100000101020101010101010000000000000000FFFFFF000000020101020200010100"
	um.VOD = startVOD
	err := um.AddSUMSToVOD()
	if err != nil {
		t.Error(err)
	}

	vod, err := hex.DecodeString(um.VOD)
	if err != nil {
		t.Error(err)
		return
	}
	if len(vod) != 258 {
		t.Errorf(th.TestErrorTemplate, "VOD length", 258, len(vod))
	}

	if strings.Compare(um.VOD, startVOD) == 0 {
		t.Errorf(th.TestErrorTemplate, "VOD modified", startVOD, um.VOD)
	}

	if strings.Compare(um.VOD, expected) != 0 {
		t.Errorf(th.TestErrorTemplate, "VOD expected", expected, um.VOD)
	}
}

func TestVerifyVOD(t *testing.T) {
	t.Skip()
	// t.Skip()
	// ICC Current
	// startVOD := "01002299084000000000002000000000000000000000010100000000000000ffffffff000001000101000101000000010001010100000000010000000000000000000000000000000000000000000000000000000001000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f2"
	// Alex's
	// startVOD := "00A92301084000000101012200010101010001010101000000000000000000FF7EFF7F000101010101000101010100010001010101000101010100000000000000000000000000010101000100000100010101000201010101000101020101000101010200010101010101010101000101000100010001010101010101010101010000000000000100000101020101010101010000000000000000FFFFFF000000020101020200010100"
	// Murlidhar's
	// startVOD := "00002301084000000101012200010101010001010101000000000000000000FF7EFF7F000101010101000101010100010001010101000101010100000000000000000000000000010101000100000100010101000201010101000101020101000101010200010101010101010101000101000100010001010101010101010101010000000000000100010101020101010101010000000000000000FFFFFF000101020101020200010100000000000000000000000000000000000000000000000000000000"
	// Initial VOD unit test
	// startVOD := "00a62299027600000101012200010100010001010101000000000000000000fffeffff000101010101010101010100010001010101000101010100000000000000000000000000010101000100000100010101000201010101000101020101000101010200010101010101010101000101010100010001010101010101010201010000000000000100000101ff00000001010200000000000003ffffffff000000020101020000010000"
	// DSA test
	startVOD := "00A92301084000000101012200010101010001010101000000000000000000FF7EFF7F000101010101000101010100010001010101000101010100000000000000000000000000010101000100000100010101000201010101000101020101000101010200010101010101010101000101000100010001010101010101010101010000000000000100000101020101010101010000000000000000FFFFFF00000002010102020001015F"
	vod, err := hex.DecodeString(startVOD)
	if err != nil {
		t.Error(err)
		return
	}

	helper := v.NewVODHelper(false, false, false)
	new_vod := helper.AddLengthAndCRC(vod[2 : len(vod)-1])

	t.Error("original", startVOD)
	t.Error("new", hex.EncodeToString(new_vod))
}

func TestAddVOD(t *testing.T) {
	cdsMap := map[string]string{
		"VOD": "1234",
		"abc": "567",
	}

	um := common.UpdateManifest{}
	um.AddVOD(cdsMap)
	v, ok := cdsMap["vod"]
	if ok {
		t.Log(v)
		t.Fail()
		return
	}

	um.VOD = ""
	um.AddVOD(cdsMap)
}
