/*
 * Copyright (C) 2016 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 "AnimationParser.h"

#include <android-base/stringprintf.h>
#include <android-base/strings.h>

#include <cutils/klog.h>

#include "animation.h"

#define LOGE(x...) do { KLOG_ERROR("charger", x); } while (0)
#define LOGW(x...) do { KLOG_WARNING("charger", x); } while (0)
#define LOGV(x...) do { KLOG_DEBUG("charger", x); } while (0)

namespace android {

// Lines consisting of only whitespace or whitespace followed by '#' can be ignored.
bool can_ignore_line(const char* str) {
    for (int i = 0; str[i] != '\0' && str[i] != '#'; i++) {
        if (!isspace(str[i])) return false;
    }
    return true;
}

bool remove_prefix(const std::string& line, const char* prefix, const char** rest) {
    const char* str = line.c_str();
    int start;
    char c;

    std::string format = base::StringPrintf(" %s%%n%%c", prefix);
    if (sscanf(str, format.c_str(), &start, &c) != 1) {
        return false;
    }

    *rest = &str[start];
    return true;
}

bool parse_text_field(const char* in, animation::text_field* field) {
    int* x = &field->pos_x;
    int* y = &field->pos_y;
    int* r = &field->color_r;
    int* g = &field->color_g;
    int* b = &field->color_b;
    int* a = &field->color_a;

    int start = 0, end = 0;

    if (sscanf(in, "c c %d %d %d %d %n%*s%n", r, g, b, a, &start, &end) == 4) {
        *x = CENTER_VAL;
        *y = CENTER_VAL;
    } else if (sscanf(in, "c %d %d %d %d %d %n%*s%n", y, r, g, b, a, &start, &end) == 5) {
        *x = CENTER_VAL;
    } else if (sscanf(in, "%d c %d %d %d %d %n%*s%n", x, r, g, b, a, &start, &end) == 5) {
        *y = CENTER_VAL;
    } else if (sscanf(in, "%d %d %d %d %d %d %n%*s%n", x, y, r, g, b, a, &start, &end) != 6) {
        return false;
    }

    if (end == 0) return false;

    field->font_file.assign(&in[start], end - start);

    return true;
}

bool parse_animation_desc(const std::string& content, animation* anim) {
    static constexpr const char* animation_prefix = "animation: ";
    static constexpr const char* fail_prefix = "fail: ";
    static constexpr const char* clock_prefix = "clock_display: ";
    static constexpr const char* percent_prefix = "percent_display: ";
    static constexpr const char* frame_prefix = "frame: ";

    std::vector<animation::frame> frames;

    for (const auto& line : base::Split(content, "\n")) {
        animation::frame frame;
        const char* rest;

        if (can_ignore_line(line.c_str())) {
            continue;
        } else if (remove_prefix(line, animation_prefix, &rest)) {
            int start = 0, end = 0;
            if (sscanf(rest, "%d %d %n%*s%n", &anim->num_cycles, &anim->first_frame_repeats,
                    &start, &end) != 2 ||
                end == 0) {
                LOGE("Bad animation format: %s\n", line.c_str());
                return false;
            } else {
                anim->animation_file.assign(&rest[start], end - start);
            }
        } else if (remove_prefix(line, fail_prefix, &rest)) {
            anim->fail_file.assign(rest);
        } else if (remove_prefix(line, clock_prefix, &rest)) {
            if (!parse_text_field(rest, &anim->text_clock)) {
                LOGE("Bad clock_display format: %s\n", line.c_str());
                return false;
            }
        } else if (remove_prefix(line, percent_prefix, &rest)) {
            if (!parse_text_field(rest, &anim->text_percent)) {
                LOGE("Bad percent_display format: %s\n", line.c_str());
                return false;
            }
        } else if (sscanf(line.c_str(), " frame: %d %d %d",
                &frame.disp_time, &frame.min_level, &frame.max_level) == 3) {
            frames.push_back(std::move(frame));
        } else {
            LOGE("Malformed animation description line: %s\n", line.c_str());
            return false;
        }
    }

    if (anim->animation_file.empty() || frames.empty()) {
        LOGE("Bad animation description. Provide the 'animation: ' line and at least one 'frame: ' "
             "line.\n");
        return false;
    }

    anim->num_frames = frames.size();
    anim->frames = new animation::frame[frames.size()];
    std::copy(frames.begin(), frames.end(), anim->frames);

    return true;
}

}  // namespace android
