// SPDX-FileCopyrightText: 2022 Iconica
//
// SPDX-License-Identifier: BSD-3-Clause

import 'package:flutter/material.dart';
import 'package:flutter_timetable/src/models/table_theme.dart';

class Table extends StatelessWidget {
  /// The [Table] to draw an overview of timerange with corresponding hour lines
  const Table({
    required this.startHour,
    required this.endHour,
    this.hoursOffset = 0,
    this.size,
    this.tableDirection = Axis.vertical,
    this.hourDimension = 80,
    this.tableOffset = 20,
    this.theme = const TableTheme(),
    super.key,
  });

  /// The [Axis] in which the table is layed out.
  final Axis tableDirection;

  /// The [Size] used for the table rendering.
  final Size? size;

  /// The hour the table starts at.
  final int startHour;

  /// The hour the table ends at.
  final int endHour;

  /// The time offset to increase all hour labels with
  final int hoursOffset;

  /// The length in pixel of a single hour in the table.
  final double hourDimension;

  /// The offset of the table;
  final double tableOffset;

  /// The theme used by the table.
  final TableTheme theme;

  @override
  Widget build(BuildContext context) {
    // calculate the textheight of the hour indicator
    var textSize = calculateTextHeight(context);
    if (tableDirection == Axis.horizontal) {
      return Row(
        children: [
          for (var i = startHour; i <= endHour; i++) ...[
            SizedBox(
              width: (i == endHour) ? hourDimension / 2 : hourDimension,
              child: Row(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Column(
                    children: [
                      Text(
                        '${(((i + hoursOffset) == 24) ? '00' : ((i + hoursOffset) % 24).toString()).padLeft(2, '0')}'
                        ':00',
                        style: theme.timeStyle ??
                            Theme.of(context).textTheme.bodyLarge,
                      ),
                      SizedBox(height: theme.tableTextOffset),
                      Container(
                        color: theme.lineColor,
                        width: theme.lineStrokeWidth,
                        height: (size ?? MediaQuery.of(context).size).height -
                            textSize.dy -
                            theme.tableTextOffset,
                      ),
                    ],
                  ),
                  // if not the last block
                  if (i != endHour) ...[
                    SizedBox(
                      width: hourDimension / 2 -
                          textSize.dx / 2 -
                          theme.lineStrokeWidth,
                    ),
                    Column(
                      mainAxisAlignment: MainAxisAlignment.start,
                      children: [
                        SizedBox(
                          height: textSize.dy + theme.tableTextOffset,
                        ),
                        // draw dotted line
                        for (int i = 0;
                            i <
                                (((size ?? MediaQuery.of(context).size)
                                            .height) -
                                        textSize.dy -
                                        theme.tableTextOffset -
                                        theme.lineDashDistance) /
                                    ((theme.lineDashLength +
                                            theme.lineDashDistance) /
                                        2);
                            i++) ...[
                          Container(
                            width: theme.lineStrokeWidth,
                            height: i.isEven
                                ? theme.lineDashLength
                                : theme.lineDashDistance,
                            color:
                                i.isEven ? theme.lineColor : Colors.transparent,
                          ),
                        ],
                      ],
                    ),
                  ],
                ],
              ),
            ),
          ],
        ],
      );
    }
    return Column(
      children: [
        for (int i = startHour; i <= endHour; i++) ...[
          SizedBox(
            height: i == endHour ? hourDimension / 2 : hourDimension,
            child: Column(
              children: [
                Row(
                  children: [
                    Text(
                      '${((i + hoursOffset) % 24).toString().padLeft(2, '0')}:00',
                      style: theme.timeStyle ??
                          Theme.of(context).textTheme.bodyLarge,
                    ),
                    SizedBox(
                      width: theme.tableTextOffset,
                    ),
                    Expanded(
                      child: Container(
                        height: theme.lineStrokeWidth,
                        color: theme.lineColor,
                      ),
                    )
                  ],
                ),
                if (i != endHour) ...[
                  const Spacer(),
                  Container(
                    margin: EdgeInsets.only(
                      left: tableOffset,
                    ),
                    height: theme.lineStrokeWidth,
                    child: Row(
                      children: [
                        for (int i = 0;
                            i <
                                ((size ?? MediaQuery.of(context).size).width -
                                        tableOffset -
                                        textSize.dx / 2) /
                                    ((theme.lineDashLength +
                                            theme.lineDashDistance) /
                                        2);
                            i++) ...[
                          Container(
                            width: i.isEven
                                ? theme.lineDashLength
                                : theme.lineDashDistance,
                            height: theme.lineStrokeWidth,
                            color:
                                i.isEven ? theme.lineColor : Colors.transparent,
                          ),
                        ],
                      ],
                    ),
                  ),
                  const Spacer(),
                ],
              ],
            ),
          ),
        ],
      ],
    );
  }

  Offset calculateTextHeight(BuildContext context, {String text = '00:00'}) {
    var textPainter = TextPainter(
      text: TextSpan(
        text: text,
        style: theme.timeStyle ?? Theme.of(context).textTheme.bodyLarge,
      ),
      textDirection: TextDirection.ltr,
    )..layout();
    return Offset(textPainter.width, textPainter.height);
  }
}
