// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Implementation of imgstatus which returns the update status of the instance

package imgstatus

import (
	"bytes"
	"fmt"
	"github.com/golang/protobuf/proto"
	"io"
	"io/ioutil"
	"policy-manager/pkg/configfetcher"
	"policy-manager/pkg/devicepolicy"
	"policy-manager/pkg/updateengine"
	"policy-manager/protos"
	"regexp"
	"strconv"
	"strings"
)

// Constants related to lsb-release file.
const (
	lsbChromeOSReleaseKey          = "CHROMEOS_RELEASE_VERSION"
	lsbChromeOSReleaseChannelKey   = "CHROMEOS_RELEASE_TRACK"
	lsbChromeOSReleaseMilestoneKey = "CHROMEOS_RELEASE_CHROME_MILESTONE"
	updateEngineCmd                = "update_engine_client"
)

// parseKeyValuePairs parses text with the form
//      key1=value1
//      key2=value2
//      ...
// into a map.
// All keys must have the format: "[a-zA-Z_]*".
// Any non-conforming lines are ignored.
func parseKeyValuePairs(reader io.Reader) (map[string]string, error) {
	content, err := ioutil.ReadAll(reader)
	if err != nil {
		return nil, err
	}

	pairs := make(map[string]string)

	// Regexp for matching key-value pairs.
	matchPair := regexp.MustCompile(`[a-zA-Z_]*=.*$`)

	// Extract release version string.
	lines := strings.Split(string(content), "\n")
	for _, line := range lines {
		line = strings.TrimSpace(line)
		if matchPair.MatchString(line) {
			pair := strings.Split(line, "=")
			key := strings.TrimSpace(pair[0])
			val := strings.TrimSpace(pair[1])
			pairs[key] = val
		}
	}

	return pairs, nil
}

// convertOSReleaseChannel takes in a release channel string from the
// lsb-release file and converts it into a ReleaseChannel type.
// If the release channel string cannot be parsed,
// RELEASE_CHANNEL_UNSPECIFIED will be returned.
func convertOSReleaseChannel(channelString string) protos.ReleaseChannel {
	// Regexp for matching release channel strings.
	// Release channel strings have the format "<name>-channel". For
	// example, "dev-channel".
	pattern := `^([a-z]{1,}-channel)$`
	matchVersionString := regexp.MustCompile(pattern)

	// Check we have a valid release channel string.
	if matchVersionString.MatchString(channelString) {
		ch := strings.ToUpper(strings.Split(channelString, "-")[0])
		if c, ok := protos.ReleaseChannel_value[ch]; ok {
			return protos.ReleaseChannel(c)
		}
	}

	// Unable to parse release channel.
	return protos.ReleaseChannel_RELEASE_CHANNEL_UNSPECIFIED
}

// parseOSInfoFromLSB returns the current OS version and release channel as
// provided by the lsb-release file. An error is returned only if the lsb file
// cannot be parsed.
func parseOSInfoFromLSB(lsbFile string) (*protos.OSVersion, error) {
	content, err := ioutil.ReadFile(lsbFile)
	if err != nil {
		return nil, err
	}

	// Parse lsb-release file as key value pairs.
	pairs, err := parseKeyValuePairs(bytes.NewReader(content))
	if err != nil {
		return nil, fmt.Errorf("unable to parse '%s': %s", lsbFile, err)
	}

	osVersion := new(protos.OSVersion)

	// Get release version string.
	if version, ok := pairs[lsbChromeOSReleaseKey]; ok {
		osVersion.VersionString = proto.String(version)
	}

	// Get the release channel.
	if channel, ok := pairs[lsbChromeOSReleaseChannelKey]; ok {
		ch := convertOSReleaseChannel(channel)
		osVersion.Channel = &ch
	}

	// Get release milestone.
	if milestone, ok := pairs[lsbChromeOSReleaseMilestoneKey]; ok {
		if n, err := strconv.ParseUint(milestone, 10, 32); err == nil {
			osVersion.Milestone = proto.Uint32(uint32(n))
		}
	}
	return osVersion, nil
}

// getStatusFromUpdateEngine returns the protos.InstanceStatus protobuf
// with the update status filled in.
func getStatusFromUpdateEngine(instanceConfigFile string, updateEngineCmd string) (*protos.InstanceStatus, error) {
	status := new(protos.InstanceStatus)

	// Check if update engine is disabled.
	config, err := devicepolicy.GetInstanceConfig(instanceConfigFile)
	if err != nil {
		return nil, fmt.Errorf("error fetching instance config: %v", err)
	}

	// Do not check update engine status if it is disabled.
	if *config.UpdateStrategy == "update_disabled" {
		status.UpdateStatus = proto.String("UPDATE_ENGINE_DISABLED")
		return status, nil
	}

	// Get response from update engine.
	response, err := updateengine.UpdateEngineStatus(updateEngineCmd)
	if err != nil {
		return nil, err
	}

	pairs, err := parseKeyValuePairs(bytes.NewReader(response))
	if err != nil {
		return nil, fmt.Errorf("unable to parse: %s", err)
	}

	// Set update status.
	if pairs["CURRENT_OP"] == "" {
		return nil, fmt.Errorf("failed to fetch update status. It is possible that update_engine has not fetched the status yet.")
	}
	status.UpdateStatus = proto.String(pairs["CURRENT_OP"])

	// Set new OS version.
	status.NewOsVersion = new(protos.OSVersion)
	status.NewOsVersion.VersionString = proto.String(pairs["NEW_VERSION"])

	// Set last update check timestamp.
	lastTime, err := strconv.ParseInt(pairs["LAST_CHECKED_TIME"], 10, 64)
	if err != nil {
		return nil, fmt.Errorf("unable to parse LAST_CHECKED_TIME: %s", err)
	}
	status.UpdateCheckTimestamp = proto.Int64(lastTime)

	return status, nil
}

// GetStatus() returns the current status of the instance as given by
// /etc/lsb-release file and update-engine.
// If an error occured, the error will be returned along with a status protobuf
// where the error field is set to the message describing the error. If the
// error field is set, all other fields other than the InstanceId are invalid.
// Note that this function must always return a status with InstanceId field
// populated regardless of whether an error occurred or not.
func GetStatus(lsbFile string, instanceConfigFile string) (*protos.InstanceStatus, error) {
	status := new(protos.InstanceStatus)
	var instanceID uint64
	id, err := configfetcher.GetInstanceID()
	if err == nil {
		instanceID = id
	}
	status.InstanceId = proto.Uint64(instanceID)

	// Get OS version from lsb-release file.
	osVersion, err := parseOSInfoFromLSB(lsbFile)
	if err != nil {
		status.Error = proto.String(err.Error())
		return status, err
	}

	status.OsVersion = osVersion

	// Get update status from update-engine via update_engine_client.
	updateStatus, err := getStatusFromUpdateEngine(instanceConfigFile, updateEngineCmd)
	if err != nil {
		status.UpdateStatus = nil
		status.Error = proto.String(err.Error())
		return status, err
	}

	proto.Merge(status, updateStatus)
	return status, nil
}
