# $Id: SVG.pm 2010-08-31 aj3 $

package Axonometrie::SVG;

use strict;
use warnings;
use 5.007;

our $VERSION = 0.01;

use XML::LibXML ();



sub new {
	my ($class, $options) = @_;
	
	if ( ! $options ) {
		croak('Required options attribute missing');
	}
	if ( ! ref $options->{graphic} || ref $options->{graphic} ne 'Axonometrie::Projection' ) {
		croak('Required "graphic" option missing');
	}
	
	my $self = {
		graphic => $options->{graphic},
	};
	bless $self, $class;
	
	$self->_createDocument();
	$self->_insertStyle();
	$self->_drawGraphic();
	
	return $self;
}



sub _createDocument() {
	my ($self) = @_;
	
	$self->{document} = XML::LibXML::Document->new('1.0', 'UTF-8');
	my $doc = $self->{document};
	
	my $root = $doc->createElementNS('http://www.w3.org/2000/svg', 'svg');
	$root->setAttribute('version', '1.1');
	$root->setAttribute('baseProfile', 'full');
	$doc->setDocumentElement($root);
}



sub _insertStyle() {
	my ($self) = @_;
	
	my $doc = $self->{document};
	my $root = $doc->documentElement;
	
	my $defs = $doc->createElement('defs');
	$root->appendChild($defs);
	
	my $style = $doc->createElement('style');
	$style->setAttribute('type', 'text/css');
	$defs->appendChild($style);
	
	my $css = <<'END';
line { stroke: black; stroke-width: .03pt; }
line.roof, line.base, line.window, line.alcove { stroke: silver; }
line.roof.front, line.door { display: none; }
line.scale { stroke: blue; }
END
	my $cdata = $doc->createCDATASection($css);
	$style->appendChild($cdata);
}



sub _drawGraphic() {
	my ($self) = @_;
	
	my $doc = $self->{document};
	my $root = $doc->documentElement;
	
	my $group = $doc->createElement('g');
	my $bounds = { minX => 0, maxX => 0, minY => 0, maxY => 0 };
	my $elements = $self->{graphic}->elements();
	foreach my $element (@$elements) {
		
		# :TODO: support more than just simple lines
		# :TODO: implement classes for 3D and 2D positions
		
		$bounds->{minX} = $element->{a}->{x} if $element->{a}->{x} < $bounds->{minX};
		$bounds->{maxX} = $element->{a}->{x} if $element->{a}->{x} > $bounds->{maxX};
		$bounds->{minY} = $element->{a}->{y} if $element->{a}->{y} < $bounds->{minY};
		$bounds->{maxY} = $element->{a}->{y} if $element->{a}->{y} > $bounds->{maxY};
		$bounds->{minX} = $element->{b}->{x} if $element->{b}->{x} < $bounds->{minX};
		$bounds->{maxX} = $element->{b}->{x} if $element->{b}->{x} > $bounds->{maxX};
		$bounds->{minY} = $element->{b}->{y} if $element->{b}->{y} < $bounds->{minY};
		$bounds->{maxY} = $element->{b}->{y} if $element->{b}->{y} > $bounds->{maxY};
		
		my $line = $doc->createElement('line');
		$line->setAttribute( 'x1', sprintf('%.3f', $element->{a}->{x}) );
		$line->setAttribute( 'y1', sprintf('%.3f', $element->{a}->{y}) );
		$line->setAttribute( 'x2', sprintf('%.3f', $element->{b}->{x}) );
		$line->setAttribute( 'y2', sprintf('%.3f', $element->{b}->{y}) );
		$line->setAttribute('class', $element->{class}) if $element->{class};
		$group->appendChild($line);
	}
	$root->appendChild($group);
	
	my $widthInCm = sprintf('%.3f', $bounds->{maxX} - $bounds->{minX} + .2);
	my $heightInCm = sprintf('%.3f', $bounds->{maxY} - $bounds->{minY} + .2);
	$root->setAttribute('width', $widthInCm . 'cm');
	$root->setAttribute('height', $heightInCm . 'cm');
	$root->setAttribute('viewBox', '0 0 ' . $widthInCm . ' ' . $heightInCm);
	$group->setAttribute('transform', 'translate(' . sprintf('%.3f', .1 - $bounds->{minX}) . ',' . sprintf('%.3f', .1 - $bounds->{minY}) . ')');
}



sub serialize {
	my ($self) = @_;
	
	return $self->{document}->serialize;
}



1;

__END__
