#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Copyright (C) 2017-2020  The Project X-Ray Authors.
#
# Use of this source code is governed by a ISC-style
# license that can be found in the LICENSE file or at
# https://opensource.org/licenses/ISC
#
# SPDX-License-Identifier: ISC

import sys
import json
import re


def main():
    db_tiles = set()
    db_tile_prop = dict()
    db_tile_sites = dict()

    db_sites = set()
    db_site_prop = dict()
    db_site_tile = dict()
    db_site_bit = dict()

    def add_tile(tile):
        if tile not in db_tiles:
            db_tiles.add(tile)
            db_tile_prop[tile] = dict()
            db_tile_sites[tile] = list()

    def add_site(site):
        if site not in db_sites:
            db_sites.add(site)
            db_site_prop[site] = dict()

    with open("%s.txt" % sys.argv[1]) as f:
        for line in f:
            line = line.split()

            if line[0] == "TILEPROP":
                add_tile(line[1])
                db_tile_prop[line[1]][line[2]] = " ".join(line[3:])
                continue

            if line[0] == "TILESITE":
                add_tile(line[1])
                add_site(line[2])
                db_tile_sites[line[1]].append(line[2])
                db_site_tile[line[2]] = line[1]
                continue

            if line[0] == "SITEPROP":
                add_site(line[1])
                db_site_prop[line[1]][line[2]] = " ".join(line[3:])
                continue

            if line[0] == "SLICEBIT":
                db_site_bit[line[1]] = line[2]
                continue

            assert False

    print("Number of tiles: %d" % len(db_tiles))
    print("Number of sites: %d" % len(db_sites))
    print("Number of sites with bit: %d" % len(db_site_bit))

    database = dict()
    loc_to_tile = dict()

    database["device"] = sys.argv[2]

    database["tiles"] = dict()
    for tile in db_tiles:
        entry = dict()
        entry["props"] = db_tile_prop[tile]
        entry["sites"] = db_tile_sites[tile]
        database["tiles"][tile] = entry

        col = int(db_tile_prop[tile]["COLUMN"])
        row = int(db_tile_prop[tile]["ROW"])
        loc_to_tile[(col, row)] = tile

    database["sites"] = dict()
    for site in db_sites:
        entry = dict()
        entry["props"] = db_site_prop[site]
        entry["tile"] = db_site_tile[site]
        database["sites"][site] = entry

    for site, bit in db_site_bit.items():
        bit = bit.split("_")
        bit_type = int(bit[4][1:])
        bit_half = int(bit[5][1:])
        bit_row = int(bit[6][1:])
        bit_col = int(bit[7][1:])
        bit_word = int(bit[9][1:])
        assert len(bit) == 11

        for i in range(50):
            m = re.match("(.*)Y([0-9]+)", site)
            this_site = "%sY%d" % (m.group(1), int(m.group(2)) + i)

            tile = db_site_tile[this_site]

            word = bit_word + 2 * i
            if word >= 50: word += 1

            entry = dict()
            entry["BASE_FRAMEID"] = "0x%08x" % (
                (bit_type << 23) | (bit_half << 22) | (bit_row << 17) |
                (bit_col << 7))
            entry["FRAME_TYPE"] = bit_type
            entry["FRAME_HALF"] = bit_half
            entry["FRAME_ROW"] = bit_row
            entry["FRAME_COLUMN"] = bit_col
            entry["WORDS"] = [word, word + 1]

            database["tiles"][tile]["cfgcol"] = entry

            if database["tiles"][tile]["props"]["TILE_TYPE"] in ("CLBLL_L",
                                                                 "CLBLM_L"):
                col = int(db_tile_prop[tile]["COLUMN"])
                row = int(db_tile_prop[tile]["ROW"])
                right_tile = loc_to_tile[(col + 1, row)]

                database["tiles"][right_tile]["cfgcol"] = entry

            if database["tiles"][tile]["props"]["TILE_TYPE"] in ("CLBLL_R",
                                                                 "CLBLM_R"):
                col = int(db_tile_prop[tile]["COLUMN"])
                row = int(db_tile_prop[tile]["ROW"])
                left_tile = loc_to_tile[(col - 1, row)]

                database["tiles"][left_tile]["cfgcol"] = entry

    tile_cfgcol_count = 0
    cfgcols = set()

    for tile in db_tiles:
        if "cfgcol" in database["tiles"][tile]:
            cfgcols.add(database["tiles"][tile]["cfgcol"]["BASE_FRAMEID"])
            tile_cfgcol_count += 1

    print("Number of assigned columns: %d" % len(cfgcols))
    print("Number of tiles with assigned column: %d" % tile_cfgcol_count)

    with open("%s.json" % sys.argv[1], "w") as f:
        print(json.dumps(database, sort_keys=True, indent="\t"), file=f)


if __name__ == "__main__":
    main()
