/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * 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.
 */

#include "HashableDimensionKey.h"
#include "dimension.h"

namespace android {
namespace os {
namespace statsd {

android::hash_t hashDimensionsValue(const DimensionsValue& value) {
    android::hash_t hash = 0;
    hash = android::JenkinsHashMix(hash, android::hash_type(value.field()));

    hash = android::JenkinsHashMix(hash, android::hash_type((int)value.value_case()));
    switch (value.value_case()) {
        case DimensionsValue::ValueCase::kValueStr:
            hash = android::JenkinsHashMix(
                    hash,
                    static_cast<uint32_t>(std::hash<std::string>()(value.value_str())));
            break;
        case DimensionsValue::ValueCase::kValueInt:
            hash = android::JenkinsHashMix(hash, android::hash_type(value.value_int()));
            break;
        case DimensionsValue::ValueCase::kValueLong:
            hash = android::JenkinsHashMix(
                    hash, android::hash_type(static_cast<int64_t>(value.value_long())));
            break;
        case DimensionsValue::ValueCase::kValueBool:
            hash = android::JenkinsHashMix(hash, android::hash_type(value.value_bool()));
            break;
        case DimensionsValue::ValueCase::kValueFloat: {
            float floatVal = value.value_float();
            hash = android::JenkinsHashMixBytes(hash, (uint8_t*)&floatVal, sizeof(float));
            break;
        }
        case DimensionsValue::ValueCase::kValueTuple: {
            hash = android::JenkinsHashMix(hash, android::hash_type(
                value.value_tuple().dimensions_value_size()));
            for (int i = 0; i < value.value_tuple().dimensions_value_size(); ++i) {
                hash = android::JenkinsHashMix(
                    hash,
                    hashDimensionsValue(value.value_tuple().dimensions_value(i)));
            }
            break;
        }
        case DimensionsValue::ValueCase::VALUE_NOT_SET:
            break;
    }
    return JenkinsHashWhiten(hash);
}

using std::string;


string HashableDimensionKey::toString() const {
    string flattened;
    DimensionsValueToString(getDimensionsValue(), &flattened);
    return flattened;
}

bool compareDimensionsValue(const DimensionsValue& s1, const DimensionsValue& s2) {
    if (s1.field() != s2.field()) {
        return false;
    }
    if (s1.value_case() != s1.value_case()) {
        return false;
    }
    switch (s1.value_case()) {
        case DimensionsValue::ValueCase::kValueStr:
            return (s1.value_str() == s2.value_str());
        case DimensionsValue::ValueCase::kValueInt:
            return s1.value_int() == s2.value_int();
        case DimensionsValue::ValueCase::kValueLong:
            return s1.value_long() == s2.value_long();
        case DimensionsValue::ValueCase::kValueBool:
            return s1.value_bool() == s2.value_bool();
        case DimensionsValue::ValueCase::kValueFloat:
            return s1.value_float() == s2.value_float();
        case DimensionsValue::ValueCase::kValueTuple:
            {
                if (s1.value_tuple().dimensions_value_size() !=
                        s2.value_tuple().dimensions_value_size()) {
                    return false;
                }
                bool allMatched = true;
                for (int i = 0; allMatched && i < s1.value_tuple().dimensions_value_size(); ++i) {
                    allMatched &= compareDimensionsValue(s1.value_tuple().dimensions_value(i),
                                                    s2.value_tuple().dimensions_value(i));
                }
                return allMatched;
            }
        case DimensionsValue::ValueCase::VALUE_NOT_SET:
        default:
            return true;
    }
}

bool HashableDimensionKey::operator==(const HashableDimensionKey& that) const {
    return compareDimensionsValue(getDimensionsValue(), that.getDimensionsValue());
};

bool HashableDimensionKey::operator<(const HashableDimensionKey& that) const {
    return toString().compare(that.toString()) < 0;
};

}  // namespace statsd
}  // namespace os
}  // namespace android