//*****************************************************************************
// Copyright 2017-2019 Intel Corporation
//
// 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 <sstream>
#include <vector>

#include "header_rewrite.hpp"
#include "util.hpp"

using namespace std;

// This function rewrites all of the
// #include "../../blah"
// into something with a dotless relative path. It seems that clang can't handle the .. stuff
// when the header files are stored in its in-memory filesystem.
// Eigen has a lot of .. in their header files.
const string rewrite_header(const string& s, const string& path)
{
    string line = s;
    // only interested in lines starging with '#include' so 8 chars minimum
    if (line.size() > 8)
    {
        // skip whitespace
        size_t pos = line.find_first_not_of(" \t");
        if (pos != string::npos && line[pos] == '#' && pos < line.size() - 7)
        {
            string directive = line;
            pos = directive.find_first_not_of(" \t", pos + 1);
            if (pos != string::npos)
            {
                directive = directive.substr(pos);
            }
            pos = directive.find_first_of(" \t", pos + 1);
            directive = directive.substr(0, pos);
            if (directive == "include")
            {
                auto line_offset = line.find_first_of("\"<");
                if (line_offset != string::npos)
                {
                    string include = line.substr(line_offset);
                    string contents = include.substr(1, include.size() - 2);
                    if (include[1] == '.')
                    {
                        if (include[2] == '/')
                        {
                            // include starts with './'
                            // rewrite "./blah.h" to "blah.h"
                            contents = contents.substr(2);
                        }
                        else
                        {
                            // include starts with '../'
                            // count number of '../' in string
                            size_t offset = 0;
                            size_t depth = 0;
                            while (contents.substr(offset, 3) == "../")
                            {
                                depth++;
                                offset += 3;
                            }
                            string trimmed = contents.substr(offset);
                            vector<string> parts = split(path, '/');
                            parts.pop_back();
                            size_t result_depth = parts.size() - depth;
                            string added_path;
                            for (size_t i = 0; i < result_depth; i++)
                            {
                                added_path += parts[i] + "/";
                            }
                            contents = added_path + trimmed;
                        }
                        if (include[0] == '<')
                        {
                            line = "#include <" + contents + ">";
                        }
                        else
                        {
                            line = "#include \"" + contents + "\"";
                        }
                    }
                }
            }
        }
    }
    return line + "\n";
}
