require 'spec_helper'

describe Squib::LayoutParser do

  it 'loads a normal layout with no extends' do
    layout = Squib::LayoutParser.load_layout(layout_file('no-extends.yml'))
    expect(layout).to eq({'frame' => {
            'x' => 38,
            'valign' => :middle,
            'str' => 'blah',
            'font' => 'Mr. Font',
            }
          }
        )
  end

  it 'loads with a single extends' do
    layout = Squib::LayoutParser.load_layout(layout_file('single-extends.yml'))
    expect(layout).to eq({'frame' => {
            'x' => 38,
            'y' => 38,
            },
          'title' => {
            'extends' => 'frame',
            'x' => 38,
            'y' => 50,
            'width' => 100,
            }
          }
        )
  end

  it 'applies the extends regardless of order' do
    layout = Squib::LayoutParser.load_layout(layout_file('pre-extends.yml'))
    expect(layout).to eq({'frame' => {
            'x' => 38,
            'y' => 38,
            },
          'title' => {
            'extends' => 'frame',
            'x' => 38,
            'y' => 50,
            'width' => 100,
            }
          }
        )
  end

  it 'applies the single-level extends multiple times' do
    layout = Squib::LayoutParser.load_layout(layout_file('single-level-multi-extends.yml'))
    expect(layout).to eq({'frame' => {
            'x' => 38,
            'y' => 38,
            },
          'title' => {
            'extends' => 'frame',
            'x' => 38,
            'y' => 50,
            'width' => 100,
            },
          'title2' => {
            'extends' => 'frame',
            'x' => 75,
            'y' => 150,
            'width' => 150,
            },
          }
        )
  end

  it 'applies multiple extends in a single rule' do
    layout = Squib::LayoutParser.load_layout(layout_file('multi-extends-single-entry.yml'))
    expect(layout).to eq({'aunt' => {
            'a' => 101,
            'b' => 102,
            'c' => 103,
            },
          'uncle' => {
            'x' => 104,
            'y' => 105,
            'b' => 106,
            },
          'child' => {
            'extends' => ['uncle','aunt'],
            'a' => 107, # my own
            'b' => 102, # from the younger aunt
            'c' => 103, # from aunt
            'x' => 108, # my own
            'y' => 105, # from uncle
            },
          }
        )
  end

  it 'applies multi-level extends' do
    layout = Squib::LayoutParser.load_layout(layout_file('multi-level-extends.yml'))
    expect(layout).to eq({'frame' => {
            'x' => 38,
            'y' => 38,
            },
          'title' => {
            'extends' => 'frame',
            'x' => 38,
            'y' => 50,
            'width' => 100,
            },
          'subtitle' => {
            'extends' => 'title',
            'x' => 38,
            'y' => 150,
            'width' => 100,
            },
          }
        )
  end

  it 'fails on a self-circular extends' do
    file = layout_file('self-circular-extends.yml')
    expect { Squib::LayoutParser.load_layout(file) }
      .to raise_error(RuntimeError, 'Invalid layout: circular extends with \'a\'')
  end

  it 'fails on a easy-circular extends' do
    file = layout_file('easy-circular-extends.yml')
    expect { Squib::LayoutParser.load_layout(file) }
      .to raise_error(RuntimeError, 'Invalid layout: circular extends with \'a\'')
  end

  it 'hard on a easy-circular extends' do
    file = layout_file('hard-circular-extends.yml')
    expect { Squib::LayoutParser.load_layout(file) }
      .to raise_error(RuntimeError, 'Invalid layout: circular extends with \'a\'')
  end

  it 'redefines keys on multiple layouts' do
    a = layout_file('multifile-a.yml')
    b = layout_file('multifile-b.yml')
    layout = Squib::LayoutParser.load_layout([a, b])
    expect(layout).to eq({
        'title'    => { 'x' => 300 },
        'subtitle' => { 'x' => 200 },
        'desc'     => { 'x' => 400 }
        })
  end

  it 'evaluates extends on each file first' do
    a = layout_file('multifile-extends-a.yml')
    b = layout_file('multifile-extends-b.yml')
    layout = Squib::LayoutParser.load_layout([a, b])
    expect(layout).to eq({
        'grandparent' => { 'x' => 100 },
        'parent_a'    => { 'x' => 110, 'extends' => 'grandparent' },
        'parent_b'    => { 'x' => 130, 'extends' => 'grandparent' },
        'child_a'     => { 'x' => 113, 'extends' => 'parent_a' },
        'child_b'     => { 'x' => 133, 'extends' => 'parent_b' }
        })
  end

  it 'loads nothing on an empty layout file' do
    layout = Squib::LayoutParser.load_layout(layout_file('empty.yml'))
    expect(layout).to eq({})
  end

  it 'handles extends on a rule with no args' do
    layout = Squib::LayoutParser.load_layout(layout_file('empty-rule.yml'))
    expect(layout).to eq({
      'empty' => nil
    })
  end

  it 'logs an error when a file is not found' do
    expect(Squib.logger).to receive(:error).once
    Squib::LayoutParser.load_layout('yeti')
  end

  it 'freaks out if you extend something doesn\'t exist' do
    expect(Squib.logger)
      .to receive(:error)
      .with("Processing layout: 'verbal' attempts to extend a missing 'kaisersoze'")
    layout = Squib::LayoutParser.load_layout(layout_file('extends-nonexists.yml'))
    expect(layout).to eq({
      'verbal'  => {
          'font_size' => 25,
          'extends' => 'kaisersoze'
        }
      })
  end

end