/*
 * Copyright (C) 2015 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 <iostream>
#include <sstream>

#include "Scanner.h"
#include "Specification.h"
#include "Utilities.h"

using namespace std;

// Maximum of errors we'll report before bailing out.
const int MAX_ERRORS = 10;

Scanner::Scanner(const string& fileName, FILE* file)
    : mFileName(fileName), mFile(file), mLineNumber(0), mTagConsumed(true), mErrorCount(0) {
}

bool Scanner::atEnd() {
    return (mTagConsumed && feof(mFile)) || mErrorCount > MAX_ERRORS;
}

int Scanner::getChar() {
    int c = fgetc(mFile);
    if (c == '\n') {
        mLineNumber++;
    }
    return c;
}

void Scanner::readUpTo(char delimiter, string* segment) {
    for (;;) {
        int c = getChar();
        if (c == EOF || c == '\n') {
            break;
        }
        segment->push_back((char)c);
        if (c == delimiter) {
            break;
        }
    }
}

void Scanner::readRestOfLine(string* segment) {
    for (;;) {
        int c = getChar();
        if (c == EOF || c == '\n') {
            return;
        }
        segment->push_back((char)c);
    }
}

bool Scanner::getNextEntry() {
    mTag.clear();
    mValue.clear();
    for (;;) {
        int c = getChar();
        if (c == EOF) {
            return false;
        }
        if (c == '#') {
            // Skip the comment
            string comment;
            readRestOfLine(&comment);
            continue;
        }
        if (c == ' ') {
            readRestOfLine(&mValue);
            break;
        } else if (c == '\n') {
            break;
        } else {
            mTag = c;
            readUpTo(':', &mTag);
            readRestOfLine(&mValue);
            trimSpaces(&mValue);
            break;
        }
    }
    return true;
}

ostream& Scanner::error() {
    return error(mLineNumber);
}

ostream& Scanner::error(int lineNumber) {
    if (++mErrorCount <= MAX_ERRORS) {
        cerr << mFileName << ":" << lineNumber << ": error: ";
    }
    return cerr;
}

void Scanner::skipBlankEntries() {
    while (findOptionalTag("")) {
        if (!mValue.empty()) {
            error() << "Unexpected: \" " << mValue << "\".\n";
        }
    }
}

bool Scanner::findTag(const char* tag) {
    bool found = findOptionalTag(tag);
    if (!found) {
        error() << "Found \"" << mTag << "\" while looking for \"" << tag << "\".\n";
    }
    mTagConsumed = true;
    return found;
}

bool Scanner::findOptionalTag(const char* tag) {
    if (mTagConsumed) {
        if (!getNextEntry()) {
            return false;
        }
    }
    mTagConsumed = (mTag == tag);
    return mTagConsumed;
}

void Scanner::checkNoValue() {
    if (!mValue.empty()) {
        error() << "Did not expect \"" << mValue << "\" after \"" << mTag << "\".\n";
    }
}

void Scanner::parseDocumentation(string* s, string* documentation) {
    size_t docStart = s->find(", \"");
    if (docStart == string::npos) {
        documentation->erase();
    } else {
        size_t first = docStart + 3;
        size_t last = s->find('\"', first);
        if (last == string::npos) {
            error() << "Missing closing double quote\n";
        }
        *documentation = s->substr(first, last - first);
        s->erase(docStart);
    }
}

ParameterEntry* Scanner::parseArgString(bool isReturn) {
    string s = mValue;
    ParameterEntry* p = new ParameterEntry();
    parseDocumentation(&s, &p->documentation);

    size_t optionStart = s.find(", ");
    if (optionStart != string::npos) {
        p->testOption = s.substr(optionStart + 2);
        s.erase(optionStart);
    }

    trimSpaces(&s);
    if (!isReturn) {
        size_t nameStart = s.rfind(' ');
        if (nameStart == string::npos) {
            error() << "Missing variable name\n";
        } else {
            p->name = s.substr(nameStart + 1);
            s.erase(nameStart);
            if (p->name.find('*') != string::npos) {
                error() << "The '*' should be attached to the type\n";
            }
        }
    }

    if (s == "void" && !isReturn) {
        error() << "void is only allowed for ret:\n";
    }
    p->type = s;
    p->lineNumber = mLineNumber;
    return p;
}
