#!/usr/bin/perl
use strict;
use warnings;
use utf8;

# binmode STDIN, ':encoding(utf8)';
# binmode STDOUT, ':encoding(utf8)';
binmode STDERR, ':encoding(utf8)';

# 曜日リストを用いて第一引数が1-12の数字のとき、
# calendar.txtにカレンダーを出力するプログラム

# サブルーチン ---
sub calendar{
    my ($month) = $_[0];
    my @week = qw(mon tue wed thu fri sat sun);
    my $week_count = 0;
    my $str;

    # 2月は28日, 4,6,9,11月は30日, 1,3,5,7,8,10,12月は31日
    my %month_have_day = ('1'=>31, '2'=>28, '3'=>31, '4'=>30, '5'=>31, '6'=>30, 
        '7'=> 31, '8'=> 31, '9'=> 30, '10'=> 31, '11'=> 30, '12'=> 31);
    
    my %first_day_of_week = ('1'=>'sun', '2'=>'wed', '3'=>'wed', '4'=> 'sat', '5'=> 'mon', '6'=> 'thu', 
        '7'=> 'sat', '8'=> 'tue', '9'=> 'fri', '10'=> 'sun', '11'=> 'wed', '12'=> 'fri');
    
    # 曜日出力
    foreach my $i(@week){
        $str .= sprintf("%s ", $i);
    }
    $str .= sprintf("\n");

    # 日曜日以外から始まる場合にははじめに一定回数の空白を入れる
    while ($week[$week_count] ne $first_day_of_week{$month}){
        $str .= sprintf("    ");
        $week_count++;
    } 

    # 日出力
    for (my $day = 1; $day <= $month_have_day{$month}; $day++){
        $str .= sprintf("%3d ", $day);
        # 日曜日を出力したら改行
        if ($week[$week_count % 7] eq 'sun'){
            $str .= sprintf("\n");
        }
        $week_count++;
    }

    $str .= sprintf("\n");
    printf("month: %d\n%s", $month, $str);
    open (FILE, '> calendar.txt') or die "$!";
    print FILE ($str);
    close (FILE);
}

# メイン ---
# 引数が一つか
my $argc = @ARGV;
if ($argc != 1){
    print STDERR "引数がひとつではない.\n";
    exit(0);
}
# 第一引数が符号なし整数か
if (!($ARGV[0] =~ /^\d+$/)) {
    print STDERR "引数が符号なしの整数ではない.\n";
    exit(0);
}

# 第一引数が範囲外か
my $num = $ARGV[0];
if ($num < 1 || 12 < $num){
    print STDERR "引数が1から12の範囲内ではない.\n";
    exit(0);
}

&calendar($num);



