/*
 * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
 * Copyright (C) 2016 Furrtek
 * Copyright (C) 2022 Arjan Onwezen
 *
 * This file is part of PortaPack.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; see the file COPYING.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street,
 * Boston, MA 02110-1301, USA.
 */

#include "database.hpp"
#include "file.hpp"
#include <cstring>

namespace std {

int database::retrieve_mid_record(MidDBRecord* record, std::string search_term) {
    file_path = "AIS/mids.db";
    index_item_length = 4;
    record_length = 32;

    result = std::database::retrieve_record(file_path, index_item_length, record_length, record, search_term);

    return (result);
}

int database::retrieve_airline_record(AirlinesDBRecord* record, std::string search_term) {
    file_path = "ADSB/airlines.db";
    index_item_length = 4;
    record_length = 64;

    result = std::database::retrieve_record(file_path, index_item_length, record_length, record, search_term);

    return (result);
}

int database::retrieve_aircraft_record(AircraftDBRecord* record, std::string search_term) {
    file_path = "ADSB/icao24.db";
    index_item_length = 7;
    record_length = 146;

    result = std::database::retrieve_record(file_path, index_item_length, record_length, record, search_term);

    return (result);
}

int database::retrieve_record(std::string file_path, int index_item_length, int record_length, void* record, std::string search_term) {
    auto result = db_file.open(file_path);
    if (!result.is_valid()) {
        number_of_records = (db_file.size() / (index_item_length + record_length));  // determine number of records in file
                                                                                     // binary search tree
        int first = 0,                                                               // First search element
            last = number_of_records - 1,                                            // Last search element
            middle,                                                                  // Mid point of search
            position = -1;                                                           // Position of search value

        while (!found && first <= last) {
            middle = (first + last) / 2;  // Calculate mid point
            db_file.seek(middle * index_item_length);
            db_file.read(file_buffer, search_term.length());
            if (file_buffer == search_term) {  // If value is found at mid
                found = true;
                position = middle;
            } else if (file_buffer > search_term)  // If value is in lower half
                last = middle - 1;
            else
                first = middle + 1;  // If value is in upper half
        }

        if (found == true) {
            db_file.seek((number_of_records * index_item_length) + (position * record_length));  // seek starting after index
            db_file.read(record, record_length);
            return (DATABASE_RECORD_FOUND);
        } else {
            return (DATABASE_RECORD_NOT_FOUND);
        }

    } else
        return (DATABASE_NOT_FOUND);
}

} /* namespace std */